FAT access
[FAT support]

Collaboration diagram for FAT access:

Functions

struct fat_fs_structfat_open (struct partition_struct *partition)
void fat_close (struct fat_fs_struct *fs)
static uint8_t fat_read_header (struct fat_fs_struct *fs)
static cluster_t fat_get_next_cluster (const struct fat_fs_struct *fs, cluster_t cluster_num)
static cluster_t fat_append_clusters (struct fat_fs_struct *fs, cluster_t cluster_num, cluster_t count)
static uint8_t fat_free_clusters (struct fat_fs_struct *fs, cluster_t cluster_num)
static uint8_t fat_terminate_clusters (struct fat_fs_struct *fs, cluster_t cluster_num)
static uint8_t fat_clear_cluster (const struct fat_fs_struct *fs, cluster_t cluster_num)
static uintptr_t fat_clear_cluster_callback (uint8_t *buffer, offset_t offset, void *p)
static offset_t fat_cluster_offset (const struct fat_fs_struct *fs, cluster_t cluster_num)
static uint8_t fat_dir_entry_read_callback (uint8_t *buffer, offset_t offset, void *p)
static uint8_t fat_calc_83_checksum (const uint8_t *file_name_83)
static offset_t fat_find_offset_for_dir_entry (struct fat_fs_struct *fs, const struct fat_dir_struct *parent, const struct fat_dir_entry_struct *dir_entry)
static uint8_t fat_write_dir_entry (const struct fat_fs_struct *fs, struct fat_dir_entry_struct *dir_entry)
offset_t fat_get_fs_size (const struct fat_fs_struct *fs)
offset_t fat_get_fs_free (const struct fat_fs_struct *fs)
static uint8_t fat_get_fs_free_16_callback (uint8_t *buffer, offset_t offset, void *p)

Detailed Description

Basic functions for handling a FAT filesystem.

Function Documentation

cluster_t fat_append_clusters ( struct fat_fs_struct fs,
cluster_t  cluster_num,
cluster_t  count 
) [static]

Appends a new cluster chain to an existing one.

Set cluster_num to zero to create a completely new one.

Parameters:
[in] fs The file system on which to operate.
[in] cluster_num The cluster to which to append the new chain.
[in] count The number of clusters to allocate.
Returns:
0 on failure, the number of the first new cluster on success.

Definition at line 493 of file fat.c.

References fat_fs_struct::cluster_free, partition_struct::device_read, partition_struct::device_write, FAT16_CLUSTER_FREE, FAT16_CLUSTER_LAST_MAX, FAT32_CLUSTER_FREE, FAT32_CLUSTER_LAST_MAX, fat_free_clusters(), fat_header_struct::fat_offset, fat_header_struct::fat_size, fat_fs_struct::header, htol16(), htol32(), fat_fs_struct::partition, PARTITION_TYPE_FAT32, and partition_struct::type.

Referenced by fat_create_dir(), fat_find_offset_for_dir_entry(), fat_resize_file(), and fat_write_file().

00494 {
00495     if(!fs)
00496         return 0;
00497 
00498     device_read_t device_read = fs->partition->device_read;
00499     device_write_t device_write = fs->partition->device_write;
00500     offset_t fat_offset = fs->header.fat_offset;
00501     cluster_t count_left = count;
00502     cluster_t cluster_current = fs->cluster_free;
00503     cluster_t cluster_next = 0;
00504     cluster_t cluster_count;
00505     uint16_t fat_entry16;
00506 #if FAT_FAT32_SUPPORT
00507     uint32_t fat_entry32;
00508     uint8_t is_fat32 = (fs->partition->type == PARTITION_TYPE_FAT32);
00509 
00510     if(is_fat32)
00511         cluster_count = fs->header.fat_size / sizeof(fat_entry32);
00512     else
00513 #endif
00514         cluster_count = fs->header.fat_size / sizeof(fat_entry16);
00515 
00516     fs->cluster_free = 0;
00517     cluster_t cluster_left = cluster_count;
00518     for( cluster_left = cluster_count; cluster_left > 0; --cluster_left, ++cluster_current)
00519     {
00520         if(cluster_current < 2 || cluster_current >= cluster_count)
00521             cluster_current = 2;
00522 
00523 #if FAT_FAT32_SUPPORT
00524         if(is_fat32)
00525         {
00526             if(!device_read(fat_offset + cluster_current * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32)))
00527                 return 0;
00528         }
00529         else
00530 #endif
00531         {
00532             if(!device_read(fat_offset + cluster_current * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16)))
00533                 return 0;
00534         }
00535 
00536 #if FAT_FAT32_SUPPORT
00537         if(is_fat32)
00538         {
00539             /* check if this is a free cluster */
00540             if(fat_entry32 != HTOL32(FAT32_CLUSTER_FREE))
00541                 continue;
00542 
00543             /* If we don't need this free cluster for the
00544              * current allocation, we keep it in mind for
00545              * the next time.
00546              */
00547             if(count_left == 0)
00548             {
00549                 fs->cluster_free = cluster_current;
00550                 break;
00551             }
00552 
00553             /* allocate cluster */
00554             if(cluster_next == 0)
00555                 fat_entry32 = HTOL32(FAT32_CLUSTER_LAST_MAX);
00556             else
00557                 fat_entry32 = htol32(cluster_next);
00558 
00559             if(!device_write(fat_offset + cluster_current * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32)))
00560                 break;
00561         }
00562         else
00563 #endif
00564         {
00565             /* check if this is a free cluster */
00566             if(fat_entry16 != HTOL16(FAT16_CLUSTER_FREE))
00567                 continue;
00568 
00569             /* If we don't need this free cluster for the
00570              * current allocation, we keep it in mind for
00571              * the next time.
00572              */
00573             if(count_left == 0)
00574             {
00575                 fs->cluster_free = cluster_current;
00576                 break;
00577             }
00578 
00579             /* allocate cluster */
00580             if(cluster_next == 0)
00581                 fat_entry16 = HTOL16(FAT16_CLUSTER_LAST_MAX);
00582             else
00583                 fat_entry16 = htol16((uint16_t) cluster_next);
00584 
00585             if(!device_write(fat_offset + cluster_current * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16)))
00586                 break;
00587         }
00588 
00589         cluster_next = cluster_current;
00590         --count_left;
00591     }
00592 
00593     do
00594     {
00595         if(count_left > 0)
00596             break;
00597 
00598         /* We allocated a new cluster chain. Now join
00599          * it with the existing one (if any).
00600          */
00601         if(cluster_num >= 2)
00602         {
00603 #if FAT_FAT32_SUPPORT
00604             if(is_fat32)
00605             {
00606                 fat_entry32 = htol32(cluster_next);
00607 
00608                 if(!device_write(fat_offset + cluster_num * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32)))
00609                     break;
00610             }
00611             else
00612 #endif
00613             {
00614                 fat_entry16 = htol16((uint16_t) cluster_next);
00615 
00616                 if(!device_write(fat_offset + cluster_num * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16)))
00617                     break;
00618             }
00619         }
00620 
00621         return cluster_next;
00622 
00623     } while(0);
00624 
00625     /* No space left on device or writing error.
00626      * Free up all clusters already allocated.
00627      */
00628     fat_free_clusters(fs, cluster_next);
00629 
00630     return 0;
00631 }

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t fat_calc_83_checksum ( const uint8_t *  file_name_83  )  [static]

Calculates the checksum for 8.3 names used within the corresponding lfn directory entries.

Parameters:
[in] file_name_83 The 11-byte file name buffer.
Returns:
The checksum of the given file name.

Definition at line 1708 of file fat.c.

Referenced by fat_dir_entry_read_callback(), and fat_write_dir_entry().

01709 {
01710     uint8_t checksum = file_name_83[0];
01711     uint16_t i=0;
01712     for( i = 1; i < 11; ++i)
01713         checksum = ((checksum >> 1) | (checksum << 7)) + file_name_83[i];
01714 
01715     return checksum;
01716 }

Here is the caller graph for this function:

uint8_t fat_clear_cluster ( const struct fat_fs_struct fs,
cluster_t  cluster_num 
) [static]

Clears a single cluster.

The complete cluster is filled with zeros.

Parameters:
[in] fs The filesystem on which to operate.
[in] cluster_num The cluster to clear.
Returns:
0 on failure, 1 on success.

Definition at line 793 of file fat.c.

References fat_header_struct::cluster_size, partition_struct::device_write_interval, fat_clear_cluster_callback(), fat_cluster_offset(), fat_fs_struct::header, and fat_fs_struct::partition.

Referenced by fat_create_dir(), and fat_find_offset_for_dir_entry().

00794 {
00795     if(cluster_num < 2)
00796         return 0;
00797 
00798     offset_t cluster_offset = fat_cluster_offset(fs, cluster_num);
00799 
00800     uint8_t zero[16];
00801     memset(zero, 0, sizeof(zero));
00802     return fs->partition->device_write_interval(cluster_offset,
00803                                                 zero,
00804                                                 fs->header.cluster_size,
00805                                                 fat_clear_cluster_callback,
00806                                                 0
00807                                                );
00808 }

Here is the call graph for this function:

Here is the caller graph for this function:

uintptr_t fat_clear_cluster_callback ( uint8_t *  buffer,
offset_t  offset,
void *  p 
) [static]

Callback function for clearing a cluster.

Definition at line 816 of file fat.c.

Referenced by fat_clear_cluster().

00817 {
00818     return 16;
00819 }

Here is the caller graph for this function:

void fat_close ( struct fat_fs_struct fs  ) 

Closes a FAT filesystem.

When this function returns, the given filesystem descriptor will be invalid.

Parameters:
[in] fs The filesystem to close.
See also:
fat_open

Definition at line 291 of file fat.c.

References fat_fs_struct::partition.

Referenced by WaspSD::close().

00292 {
00293     if(!fs)
00294         return;
00295 
00296 #if USE_DYNAMIC_MEMORY
00297     free(fs);
00298 #else
00299     fs->partition = 0;
00300 #endif
00301 }

Here is the caller graph for this function:

offset_t fat_cluster_offset ( const struct fat_fs_struct fs,
cluster_t  cluster_num 
) [static]

Calculates the offset of the specified cluster.

Parameters:
[in] fs The filesystem on which to operate.
[in] cluster_num The cluster whose offset to calculate.
Returns:
The cluster offset.

Definition at line 830 of file fat.c.

References fat_header_struct::cluster_size, fat_header_struct::cluster_zero_offset, and fat_fs_struct::header.

Referenced by fat_clear_cluster(), fat_find_offset_for_dir_entry(), fat_read_dir(), fat_read_file(), and fat_write_file().

00831 {
00832     if(!fs || cluster_num < 2)
00833         return 0;
00834 
00835     return fs->header.cluster_zero_offset + (offset_t) (cluster_num - 2) * fs->header.cluster_size;
00836 }

Here is the caller graph for this function:

uint8_t fat_dir_entry_read_callback ( uint8_t *  buffer,
offset_t  offset,
void *  p 
) [static]

Callback function for reading a directory entry.

Interprets a raw directory entry and puts the contained information into a fat_dir_entry_struct structure.

For a single file there may exist multiple directory entries. All except the last one are lfn entries, which contain parts of the long filename. The last directory entry is a traditional 8.3 style one. It contains all other information like size, cluster, date and time.

Parameters:
[in] buffer A pointer to 32 bytes of raw data.
[in] offset The absolute offset of the raw data.
[in,out] p An argument structure controlling operation.
Returns:
0 on failure or completion, 1 if reading has to be continued

Definition at line 1579 of file fat.c.

References fat_dir_entry_struct::attributes, fat_read_dir_callback_arg::bytes_read, fat_read_dir_callback_arg::checksum, fat_dir_entry_struct::cluster, fat_read_dir_callback_arg::dir_entry, fat_dir_entry_struct::entry_offset, fat_calc_83_checksum(), FAT_DIRENTRY_DELETED, fat_dir_entry_struct::file_size, fat_read_dir_callback_arg::finished, fat_dir_entry_struct::long_name, ltoh16, and ltoh32.

Referenced by fat_read_dir().

01580 {
01581     struct fat_read_dir_callback_arg* arg = p;
01582     struct fat_dir_entry_struct* dir_entry = arg->dir_entry;
01583 
01584     arg->bytes_read += 32;
01585 
01586     /* skip deleted or empty entries */
01587     if(buffer[0] == FAT_DIRENTRY_DELETED || !buffer[0])
01588     {
01589 #if FAT_LFN_SUPPORT
01590         arg->checksum = 0;
01591 #endif
01592         return 1;
01593     }
01594 
01595 #if !FAT_LFN_SUPPORT
01596     /* skip lfn entries */
01597     if(buffer[11] == 0x0f)
01598         return 1;
01599 #endif
01600 
01601     char* long_name = dir_entry->long_name;
01602 #if FAT_LFN_SUPPORT
01603     if(buffer[11] == 0x0f)
01604     {
01605         /* checksum validation */
01606         if(arg->checksum == 0 || arg->checksum != buffer[13])
01607         {
01608             /* reset directory entry */
01609             memset(dir_entry, 0, sizeof(*dir_entry));
01610 
01611             arg->checksum = buffer[13];
01612             dir_entry->entry_offset = offset;
01613         }
01614 
01615         /* lfn supports unicode, but we do not, for now.
01616          * So we assume pure ascii and read only every
01617          * second byte.
01618          */
01619         uint16_t char_offset = ((buffer[0] & 0x3f) - 1) * 13;
01620         const uint8_t char_mapping[] = { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 };
01621         uint16_t i=0;
01622         for( i = 0; i <= 12 && char_offset + i < sizeof(dir_entry->long_name) - 1; ++i)
01623             long_name[char_offset + i] = buffer[char_mapping[i]];
01624 
01625         return 1;
01626     }
01627     else
01628 #endif
01629     {
01630 #if FAT_LFN_SUPPORT
01631         /* if we do not have a long name or the previous lfn does not match, take the 8.3 name */
01632         if(long_name[0] == '\0' || arg->checksum != fat_calc_83_checksum(buffer))
01633 #endif
01634         {
01635             /* reset directory entry */
01636             memset(dir_entry, 0, sizeof(*dir_entry));
01637             dir_entry->entry_offset = offset;
01638 
01639             uint8_t i;
01640             for(i = 0; i < 8; ++i)
01641             {
01642                 if(buffer[i] == ' ')
01643                     break;
01644                 long_name[i] = buffer[i];
01645 
01646                 /* Windows NT and later versions do not store lfn entries
01647                  * for 8.3 names which have a lowercase basename, extension
01648                  * or both when everything else is uppercase. They use two
01649                  * extra bits to signal a lowercase basename or extension.
01650                  */
01651                 if((buffer[12] & 0x08) && buffer[i] >= 'A' && buffer[i] <= 'Z')
01652                     long_name[i] += 'a' - 'A';
01653             }
01654             if(long_name[0] == 0x05)
01655                 long_name[0] = (char) FAT_DIRENTRY_DELETED;
01656 
01657             if(buffer[8] != ' ')
01658             {
01659                 long_name[i++] = '.';
01660 
01661                 uint8_t j = 8;
01662                 for(; j < 11; ++j)
01663                 {
01664                     if(buffer[j] == ' ')
01665                         break;
01666                     long_name[i] = buffer[j];
01667 
01668                     /* See above for the lowercase 8.3 name handling of
01669                      * Windows NT and later.
01670                      */
01671                     if((buffer[12] & 0x10) && buffer[j] >= 'A' && buffer[j] <= 'Z')
01672                         long_name[i] += 'a' - 'A';
01673 
01674                     ++i;
01675                 }
01676             } 
01677 
01678             long_name[i] = '\0';
01679         }
01680         
01681         /* extract properties of file and store them within the structure */
01682         dir_entry->attributes = buffer[11];
01683         dir_entry->cluster = ltoh16(*((uint16_t*) &buffer[26]));
01684 #if FAT_FAT32_SUPPORT
01685         dir_entry->cluster |= ((cluster_t) ltoh16(*((uint16_t*) &buffer[20]))) << 16;
01686 #endif
01687         dir_entry->file_size = ltoh32(*((uint32_t*) &buffer[28]));
01688 
01689 #if FAT_DATETIME_SUPPORT
01690         dir_entry->modification_time = ltoh16(*((uint16_t*) &buffer[22]));
01691         dir_entry->modification_date = ltoh16(*((uint16_t*) &buffer[24]));
01692 #endif
01693 
01694         arg->finished = 1;
01695         return 0;
01696     }
01697 }

Here is the call graph for this function:

Here is the caller graph for this function:

offset_t fat_find_offset_for_dir_entry ( struct fat_fs_struct fs,
const struct fat_dir_struct parent,
const struct fat_dir_entry_struct dir_entry 
) [static]

Searches for space where to store a directory entry.

Parameters:
[in] fs The filesystem on which to operate.
[in] parent The directory in which to search.
[in] dir_entry The directory entry for which to search space.
Returns:
0 on failure, a device offset on success.

Definition at line 1729 of file fat.c.

References fat_dir_entry_struct::cluster, fat_header_struct::cluster_size, fat_header_struct::cluster_zero_offset, partition_struct::device_read, fat_dir_struct::dir_entry, fat_append_clusters(), fat_clear_cluster(), fat_cluster_offset(), FAT_DIRENTRY_DELETED, fat_get_next_cluster(), fat_fs_struct::header, fat_dir_entry_struct::long_name, fat_fs_struct::partition, PARTITION_TYPE_FAT32, fat_header_struct::root_dir_offset, and partition_struct::type.

Referenced by fat_create_dir(), and fat_create_file().

01730 {
01731     if(!fs || !dir_entry)
01732         return 0;
01733 
01734     /* search for a place where to write the directory entry to disk */
01735 #if FAT_LFN_SUPPORT
01736     uint8_t free_dir_entries_needed = (strlen(dir_entry->long_name) + 12) / 13 + 1;
01737     uint8_t free_dir_entries_found = 0;
01738 #endif
01739     cluster_t cluster_num = parent->dir_entry.cluster;
01740     offset_t dir_entry_offset = 0;
01741     offset_t offset = 0;
01742     offset_t offset_to = 0;
01743 #if FAT_FAT32_SUPPORT
01744     uint8_t is_fat32 = (fs->partition->type == PARTITION_TYPE_FAT32);
01745 #endif
01746 
01747     if(cluster_num == 0)
01748     {
01749 #if FAT_FAT32_SUPPORT
01750         if(is_fat32)
01751         {
01752             cluster_num = fs->header.root_dir_cluster;
01753         }
01754         else
01755 #endif
01756         {
01757             /* we read/write from the root directory entry */
01758             offset = fs->header.root_dir_offset;
01759             offset_to = fs->header.cluster_zero_offset;
01760             dir_entry_offset = offset;
01761         }
01762     }
01763     
01764     while(1)
01765     {
01766         if(offset == offset_to)
01767         {
01768             if(cluster_num == 0)
01769                 /* We iterated through the whole root directory and
01770                  * could not find enough space for the directory entry.
01771                  */
01772                 return 0;
01773 
01774             if(offset)
01775             {
01776                 /* We reached a cluster boundary and have to
01777                  * switch to the next cluster.
01778                  */
01779 
01780                 cluster_t cluster_next = fat_get_next_cluster(fs, cluster_num);
01781                 if(!cluster_next)
01782                 {
01783                     cluster_next = fat_append_clusters(fs, cluster_num, 1);
01784                     if(!cluster_next)
01785                         return 0;
01786 
01787                     /* we appended a new cluster and know it is free */
01788                     dir_entry_offset = fs->header.cluster_zero_offset +
01789                                        (offset_t) (cluster_next - 2) * fs->header.cluster_size;
01790 
01791                     /* clear cluster to avoid garbage directory entries */
01792                     fat_clear_cluster(fs, cluster_next);
01793 
01794                     break;
01795                 }
01796                 cluster_num = cluster_next;
01797             }
01798 
01799             offset = fat_cluster_offset(fs, cluster_num);
01800             offset_to = offset + fs->header.cluster_size;
01801             dir_entry_offset = offset;
01802 #if FAT_LFN_SUPPORT
01803             free_dir_entries_found = 0;
01804 #endif
01805         }
01806         
01807         /* read next lfn or 8.3 entry */
01808         uint8_t first_char;
01809         if(!fs->partition->device_read(offset, &first_char, sizeof(first_char)))
01810             return 0;
01811 
01812         /* check if we found a free directory entry */
01813         if(first_char == FAT_DIRENTRY_DELETED || !first_char)
01814         {
01815             /* check if we have the needed number of available entries */
01816 #if FAT_LFN_SUPPORT
01817             ++free_dir_entries_found;
01818             if(free_dir_entries_found >= free_dir_entries_needed)
01819 #endif
01820                 break;
01821 
01822             offset += 32;
01823         }
01824         else
01825         {
01826             offset += 32;
01827             dir_entry_offset = offset;
01828 #if FAT_LFN_SUPPORT
01829             free_dir_entries_found = 0;
01830 #endif
01831         }
01832     }
01833 
01834     return dir_entry_offset;
01835 }

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t fat_free_clusters ( struct fat_fs_struct fs,
cluster_t  cluster_num 
) [static]

Frees a cluster chain, or a part thereof.

Marks the specified cluster and all clusters which are sequentially referenced by it as free. They may then be used again for future file allocations.

Note:
If this function is used for freeing just a part of a cluster chain, the new end of the chain is not correctly terminated within the FAT. Use fat_terminate_clusters() instead.
Parameters:
[in] fs The filesystem on which to operate.
[in] cluster_num The starting cluster of the chain which to free.
Returns:
0 on failure, 1 on success.
See also:
fat_terminate_clusters

Definition at line 652 of file fat.c.

References fat_fs_struct::cluster_free, partition_struct::device_read, partition_struct::device_write, FAT16_CLUSTER_BAD, FAT16_CLUSTER_FREE, FAT16_CLUSTER_LAST_MAX, FAT16_CLUSTER_LAST_MIN, FAT16_CLUSTER_RESERVED_MAX, FAT16_CLUSTER_RESERVED_MIN, FAT32_CLUSTER_BAD, FAT32_CLUSTER_FREE, FAT32_CLUSTER_LAST_MAX, FAT32_CLUSTER_LAST_MIN, FAT32_CLUSTER_RESERVED_MAX, FAT32_CLUSTER_RESERVED_MIN, fat_header_struct::fat_offset, fat_fs_struct::header, ltoh16, ltoh32, fat_fs_struct::partition, PARTITION_TYPE_FAT32, and partition_struct::type.

Referenced by fat_append_clusters(), fat_create_dir(), fat_delete_file(), fat_resize_file(), and fat_terminate_clusters().

00653 {
00654     if(!fs || cluster_num < 2)
00655         return 0;
00656 
00657     offset_t fat_offset = fs->header.fat_offset;
00658 #if FAT_FAT32_SUPPORT
00659     if(fs->partition->type == PARTITION_TYPE_FAT32)
00660     {
00661         uint32_t fat_entry;
00662         while(cluster_num)
00663         {
00664             if(!fs->partition->device_read(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
00665                 return 0;
00666 
00667             /* get next cluster of current cluster before freeing current cluster */
00668             uint32_t cluster_num_next = ltoh32(fat_entry);
00669 
00670             if(cluster_num_next == FAT32_CLUSTER_FREE)
00671                 return 1;
00672             if(cluster_num_next == FAT32_CLUSTER_BAD ||
00673                (cluster_num_next >= FAT32_CLUSTER_RESERVED_MIN &&
00674                 cluster_num_next <= FAT32_CLUSTER_RESERVED_MAX
00675                )
00676               )
00677                 return 0;
00678             if(cluster_num_next >= FAT32_CLUSTER_LAST_MIN && cluster_num_next <= FAT32_CLUSTER_LAST_MAX)
00679                 cluster_num_next = 0;
00680 
00681             /* We know we will free the cluster, so remember it as
00682              * free for the next allocation.
00683              */
00684             if(!fs->cluster_free)
00685                 fs->cluster_free = cluster_num;
00686 
00687             /* free cluster */
00688             fat_entry = HTOL32(FAT32_CLUSTER_FREE);
00689             fs->partition->device_write(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry));
00690 
00691             /* We continue in any case here, even if freeing the cluster failed.
00692              * The cluster is lost, but maybe we can still free up some later ones.
00693              */
00694 
00695             cluster_num = cluster_num_next;
00696         }
00697     }
00698     else
00699 #endif
00700     {
00701         uint16_t fat_entry;
00702         while(cluster_num)
00703         {
00704             if(!fs->partition->device_read(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
00705                 return 0;
00706 
00707             /* get next cluster of current cluster before freeing current cluster */
00708             uint16_t cluster_num_next = ltoh16(fat_entry);
00709 
00710             if(cluster_num_next == FAT16_CLUSTER_FREE)
00711                 return 1;
00712             if(cluster_num_next == FAT16_CLUSTER_BAD ||
00713                (cluster_num_next >= FAT16_CLUSTER_RESERVED_MIN &&
00714                 cluster_num_next <= FAT16_CLUSTER_RESERVED_MAX
00715                )
00716               )
00717                 return 0;
00718             if(cluster_num_next >= FAT16_CLUSTER_LAST_MIN && cluster_num_next <= FAT16_CLUSTER_LAST_MAX)
00719                 cluster_num_next = 0;
00720 
00721             /* free cluster */
00722             fat_entry = HTOL16(FAT16_CLUSTER_FREE);
00723             fs->partition->device_write(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry));
00724 
00725             /* We continue in any case here, even if freeing the cluster failed.
00726              * The cluster is lost, but maybe we can still free up some later ones.
00727              */
00728 
00729             cluster_num = cluster_num_next;
00730         }
00731     }
00732 
00733     return 1;
00734 }

Here is the caller graph for this function:

offset_t fat_get_fs_free ( const struct fat_fs_struct fs  ) 

Returns the amount of free storage capacity on the filesystem in bytes.

Note:
As the FAT filesystem is cluster based, this function does not return continuous values but multiples of the cluster size.
Parameters:
[in] fs The filesystem on which to operate.
Returns:
0 on failure, the free filesystem space in bytes otherwise.

Definition at line 2376 of file fat.c.

References fat_usage_count_callback_arg::buffer_size, fat_usage_count_callback_arg::cluster_count, fat_header_struct::cluster_size, partition_struct::device_read_interval, FAT_FAT32_SUPPORT, fat_get_fs_free_16_callback(), fat_header_struct::fat_offset, fat_header_struct::fat_size, fat_fs_struct::header, fat_fs_struct::partition, PARTITION_TYPE_FAT16, and partition_struct::type.

Referenced by WaspSD::getDiskFree(), and WaspSD::print_disk_info().

02377 {
02378     if(!fs)
02379         return 0;
02380 
02381     uint8_t fat[32];
02382     struct fat_usage_count_callback_arg count_arg;
02383     count_arg.cluster_count = 0;
02384     count_arg.buffer_size = sizeof(fat);
02385 
02386     offset_t fat_offset = fs->header.fat_offset;
02387     uint32_t fat_size = fs->header.fat_size;
02388     while(fat_size > 0)
02389     {
02390         uintptr_t length = UINTPTR_MAX - 1;
02391         if(fat_size < length)
02392             length = fat_size;
02393 
02394         if(!fs->partition->device_read_interval(fat_offset,
02395                                                 fat,
02396                                                 sizeof(fat),
02397                                                 length,
02398 #if FAT_FAT32_SUPPORT
02399                                                 (fs->partition->type == PARTITION_TYPE_FAT16) ?
02400                                                     fat_get_fs_free_16_callback :
02401                                                     fat_get_fs_free_32_callback,
02402 #else
02403                                                 fat_get_fs_free_16_callback,
02404 #endif
02405                                                 &count_arg
02406                                                )
02407           )
02408             return 0;
02409 
02410         fat_offset += length;
02411         fat_size -= length;
02412     }
02413 
02414     return (offset_t) count_arg.cluster_count * fs->header.cluster_size;
02415 }

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t fat_get_fs_free_16_callback ( uint8_t *  buffer,
offset_t  offset,
void *  p 
) [static]

Callback function used for counting free clusters in a FAT.

Definition at line 2421 of file fat.c.

References fat_usage_count_callback_arg::buffer_size, fat_usage_count_callback_arg::cluster_count, and FAT16_CLUSTER_FREE.

Referenced by fat_get_fs_free().

02422 {
02423     struct fat_usage_count_callback_arg* count_arg = (struct fat_usage_count_callback_arg*) p;
02424     uintptr_t buffer_size = count_arg->buffer_size;
02425 
02426     uintptr_t i = 0;
02427     for( i = 0; i < buffer_size; i += 2, buffer += 2)
02428     {
02429         uint16_t cluster = *((uint16_t*) &buffer[0]);
02430         if(cluster == HTOL16(FAT16_CLUSTER_FREE))
02431             ++(count_arg->cluster_count);
02432     }
02433 
02434     return 1;
02435 }

Here is the caller graph for this function:

offset_t fat_get_fs_size ( const struct fat_fs_struct fs  ) 

Deletes a directory.

This is just a synonym for fat_delete_file(). If a directory is deleted without first deleting its subdirectories and files, disk space occupied by these files will get wasted as there is no chance to release it and mark it as free.

Parameters:
[in] fs The filesystem on which to operate.
[in] dir_entry The directory entry of the directory to delete.
Returns:
0 on failure, 1 on success.
See also:
fat_create_dir
Returns the amount of total storage capacity of the filesystem in bytes.

Parameters:
[in] fs The filesystem on which to operate.
Returns:
0 on failure, the filesystem size in bytes otherwise.

Definition at line 2353 of file fat.c.

References fat_header_struct::cluster_size, fat_header_struct::fat_size, fat_fs_struct::header, fat_fs_struct::partition, PARTITION_TYPE_FAT32, and partition_struct::type.

Referenced by WaspSD::getDiskSize(), and WaspSD::print_disk_info().

02354 {
02355     if(!fs)
02356         return 0;
02357 
02358 #if FAT_FAT32_SUPPORT
02359     if(fs->partition->type == PARTITION_TYPE_FAT32)
02360         return (offset_t) (fs->header.fat_size / 4 - 2) * fs->header.cluster_size;
02361     else
02362 #endif
02363         return (offset_t) (fs->header.fat_size / 2 - 2) * fs->header.cluster_size;
02364 }

Here is the caller graph for this function:

cluster_t fat_get_next_cluster ( const struct fat_fs_struct fs,
cluster_t  cluster_num 
) [static]

Retrieves the next following cluster of a given cluster.

Using the filesystem file allocation table, this function returns the number of the cluster containing the data directly following the data within the cluster with the given number.

Parameters:
[in] fs The filesystem for which to determine the next cluster.
[in] cluster_num The number of the cluster for which to determine its successor.
Returns:
The wanted cluster number, or 0 on error.

Definition at line 438 of file fat.c.

References partition_struct::device_read, FAT16_CLUSTER_BAD, FAT16_CLUSTER_FREE, FAT16_CLUSTER_LAST_MAX, FAT16_CLUSTER_LAST_MIN, FAT16_CLUSTER_RESERVED_MAX, FAT16_CLUSTER_RESERVED_MIN, FAT32_CLUSTER_BAD, FAT32_CLUSTER_FREE, FAT32_CLUSTER_LAST_MAX, FAT32_CLUSTER_LAST_MIN, FAT32_CLUSTER_RESERVED_MAX, FAT32_CLUSTER_RESERVED_MIN, fat_header_struct::fat_offset, fat_fs_struct::header, ltoh16, ltoh32, fat_fs_struct::partition, PARTITION_TYPE_FAT32, and partition_struct::type.

Referenced by fat_find_offset_for_dir_entry(), fat_read_dir(), fat_read_file(), fat_resize_file(), fat_terminate_clusters(), and fat_write_file().

00439 {
00440     if(!fs || cluster_num < 2)
00441         return 0;
00442 
00443 #if FAT_FAT32_SUPPORT
00444     if(fs->partition->type == PARTITION_TYPE_FAT32)
00445     {
00446         /* read appropriate fat entry */
00447         uint32_t fat_entry;
00448         if(!fs->partition->device_read(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
00449             return 0;
00450 
00451         /* determine next cluster from fat */
00452         cluster_num = ltoh32(fat_entry);
00453         
00454         if(cluster_num == FAT32_CLUSTER_FREE ||
00455            cluster_num == FAT32_CLUSTER_BAD ||
00456            (cluster_num >= FAT32_CLUSTER_RESERVED_MIN && cluster_num <= FAT32_CLUSTER_RESERVED_MAX) ||
00457            (cluster_num >= FAT32_CLUSTER_LAST_MIN && cluster_num <= FAT32_CLUSTER_LAST_MAX))
00458             return 0;
00459     }
00460     else
00461 #endif
00462     {
00463         /* read appropriate fat entry */
00464         uint16_t fat_entry;
00465         if(!fs->partition->device_read(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
00466             return 0;
00467 
00468         /* determine next cluster from fat */
00469         cluster_num = ltoh16(fat_entry);
00470         
00471         if(cluster_num == FAT16_CLUSTER_FREE ||
00472            cluster_num == FAT16_CLUSTER_BAD ||
00473            (cluster_num >= FAT16_CLUSTER_RESERVED_MIN && cluster_num <= FAT16_CLUSTER_RESERVED_MAX) ||
00474            (cluster_num >= FAT16_CLUSTER_LAST_MIN && cluster_num <= FAT16_CLUSTER_LAST_MAX))
00475             return 0;
00476     }
00477 
00478     return cluster_num;
00479 }

Here is the caller graph for this function:

struct fat_fs_struct* fat_open ( struct partition_struct partition  )  [read]

Opens a FAT filesystem.

Parameters:
[in] partition Discriptor of partition on which the filesystem resides.
Returns:
0 on error, a FAT filesystem descriptor on success.
See also:
fat_close

Definition at line 235 of file fat.c.

References partition_struct::device_write, partition_struct::device_write_interval, FAT_FS_COUNT, fat_fs_handles, fat_read_header(), FAT_WRITE_SUPPORT, and fat_fs_struct::partition.

Referenced by WaspSD::init().

00236 {
00237     if(!partition ||
00238 #if FAT_WRITE_SUPPORT
00239        !partition->device_write ||
00240        !partition->device_write_interval
00241 #else
00242        0
00243 #endif
00244       )
00245         return 0;
00246 
00247 #if USE_DYNAMIC_MEMORY
00248     struct fat_fs_struct* fs = malloc(sizeof(*fs));
00249     if(!fs)
00250         return 0;
00251 #else
00252     struct fat_fs_struct* fs = fat_fs_handles;
00253     uint8_t i;
00254     for(i = 0; i < FAT_FS_COUNT; ++i)
00255     {
00256         if(!fs->partition)
00257             break;
00258 
00259         ++fs;
00260     }
00261     if(i >= FAT_FS_COUNT)
00262         return 0;
00263 #endif
00264 
00265     memset(fs, 0, sizeof(*fs));
00266 
00267     fs->partition = partition;
00268     if(!fat_read_header(fs))
00269     {
00270 #if USE_DYNAMIC_MEMORY
00271         free(fs);
00272 #else
00273         fs->partition = 0;
00274 #endif
00275         return 0;
00276     }
00277     
00278     return fs;
00279 }

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t fat_read_header ( struct fat_fs_struct fs  )  [static]

Reads and parses the header of a FAT filesystem.

Parameters:
inout] fs The filesystem for which to parse the header.
Returns:
0 on failure, 1 on success.

Definition at line 310 of file fat.c.

References fat_header_struct::cluster_size, fat_header_struct::cluster_zero_offset, partition_struct::device_read, fat_header_struct::fat_offset, fat_header_struct::fat_size, fat_fs_struct::header, ltoh16, ltoh32, partition_struct::offset, fat_fs_struct::partition, PARTITION_TYPE_FAT16, PARTITION_TYPE_FAT32, fat_header_struct::root_dir_offset, fat_header_struct::sector_size, fat_header_struct::size, and partition_struct::type.

Referenced by fat_open().

00311 {
00312     if(!fs)
00313         return 0;
00314 
00315     struct partition_struct* partition = fs->partition;
00316     if(!partition)
00317         return 0;
00318 
00319     /* read fat parameters */
00320 #if FAT_FAT32_SUPPORT
00321     uint8_t buffer[37];
00322 #else
00323     uint8_t buffer[25];
00324 #endif
00325     offset_t partition_offset = (offset_t) partition->offset * 512;
00326     if(!partition->device_read(partition_offset + 0x0b, buffer, sizeof(buffer)))
00327         return 0;
00328 
00329     uint16_t bytes_per_sector = ltoh16(*((uint16_t*) &buffer[0x00]));
00330     uint16_t reserved_sectors = ltoh16(*((uint16_t*) &buffer[0x03]));
00331     uint8_t sectors_per_cluster = buffer[0x02];
00332     uint8_t fat_copies = buffer[0x05];
00333     uint16_t max_root_entries = ltoh16(*((uint16_t*) &buffer[0x06]));
00334     uint16_t sector_count_16 = ltoh16(*((uint16_t*) &buffer[0x08]));
00335     uint16_t sectors_per_fat = ltoh16(*((uint16_t*) &buffer[0x0b]));
00336     uint32_t sector_count = ltoh32(*((uint32_t*) &buffer[0x15]));
00337 #if FAT_FAT32_SUPPORT
00338     uint32_t sectors_per_fat32 = ltoh32(*((uint32_t*) &buffer[0x19]));
00339     uint32_t cluster_root_dir = ltoh32(*((uint32_t*) &buffer[0x21]));
00340 #endif
00341 
00342     if(sector_count == 0)
00343     {
00344         if(sector_count_16 == 0)
00345             /* illegal volume size */
00346             return 0;
00347         else
00348             sector_count = sector_count_16;
00349     }
00350 #if FAT_FAT32_SUPPORT
00351     if(sectors_per_fat != 0)
00352         sectors_per_fat32 = sectors_per_fat;
00353     else if(sectors_per_fat32 == 0)
00354         /* this is neither FAT16 nor FAT32 */
00355         return 0;
00356 #else
00357     if(sectors_per_fat == 0)
00358         /* this is not a FAT16 */
00359         return 0;
00360 #endif
00361 
00362     /* determine the type of FAT we have here */
00363     uint32_t data_sector_count = sector_count
00364                                  - reserved_sectors
00365 #if FAT_FAT32_SUPPORT
00366                                  - sectors_per_fat32 * fat_copies
00367 #else
00368                                  - (uint32_t) sectors_per_fat * fat_copies
00369 #endif
00370                                  - ((max_root_entries * 32 + bytes_per_sector - 1) / bytes_per_sector);
00371     uint32_t data_cluster_count = data_sector_count / sectors_per_cluster;
00372     if(data_cluster_count < 4085)
00373         /* this is a FAT12, not supported */
00374         return 0;
00375     else if(data_cluster_count < 65525)
00376         /* this is a FAT16 */
00377         partition->type = PARTITION_TYPE_FAT16;
00378     else
00379         /* this is a FAT32 */
00380         partition->type = PARTITION_TYPE_FAT32;
00381 
00382     /* fill header information */
00383     struct fat_header_struct* header = &fs->header;
00384     memset(header, 0, sizeof(*header));
00385     
00386     header->size = (offset_t) sector_count * bytes_per_sector;
00387 
00388     header->fat_offset = /* jump to partition */
00389                          partition_offset +
00390                          /* jump to fat */
00391                          (offset_t) reserved_sectors * bytes_per_sector;
00392     header->fat_size = (data_cluster_count + 2) * (partition->type == PARTITION_TYPE_FAT16 ? 2 : 4);
00393 
00394     header->sector_size = bytes_per_sector;
00395     header->cluster_size = (uint16_t) bytes_per_sector * sectors_per_cluster;
00396 
00397 #if FAT_FAT32_SUPPORT
00398     if(partition->type == PARTITION_TYPE_FAT16)
00399 #endif
00400     {
00401         header->root_dir_offset = /* jump to fats */
00402                                   header->fat_offset +
00403                                   /* jump to root directory entries */
00404                                   (offset_t) fat_copies * sectors_per_fat * bytes_per_sector;
00405 
00406         header->cluster_zero_offset = /* jump to root directory entries */
00407                                       header->root_dir_offset +
00408                                       /* skip root directory entries */
00409                                       (offset_t) max_root_entries * 32;
00410     }
00411 #if FAT_FAT32_SUPPORT
00412     else
00413     {
00414         header->cluster_zero_offset = /* jump to fats */
00415                                       header->fat_offset +
00416                                       /* skip fats */
00417                                       (offset_t) fat_copies * sectors_per_fat32 * bytes_per_sector;
00418 
00419         header->root_dir_cluster = cluster_root_dir;
00420     }
00421 #endif
00422 
00423     return 1;
00424 }

Here is the caller graph for this function:

uint8_t fat_terminate_clusters ( struct fat_fs_struct fs,
cluster_t  cluster_num 
) [static]

Frees a part of a cluster chain and correctly terminates the rest.

Marks the specified cluster as the new end of a cluster chain and frees all following clusters.

Parameters:
[in] fs The filesystem on which to operate.
[in] cluster_num The new end of the cluster chain.
Returns:
0 on failure, 1 on success.
See also:
fat_free_clusters

Definition at line 750 of file fat.c.

References partition_struct::device_write, FAT16_CLUSTER_LAST_MAX, FAT32_CLUSTER_LAST_MAX, fat_free_clusters(), fat_get_next_cluster(), fat_header_struct::fat_offset, fat_fs_struct::header, fat_fs_struct::partition, PARTITION_TYPE_FAT32, and partition_struct::type.

Referenced by fat_resize_file().

00751 {
00752     if(!fs || cluster_num < 2)
00753         return 0;
00754 
00755     /* fetch next cluster before overwriting the cluster entry */
00756     cluster_t cluster_num_next = fat_get_next_cluster(fs, cluster_num);
00757 
00758     /* mark cluster as the last one */
00759 #if FAT_FAT32_SUPPORT
00760     if(fs->partition->type == PARTITION_TYPE_FAT32)
00761     {
00762         uint32_t fat_entry = HTOL32(FAT32_CLUSTER_LAST_MAX);
00763         if(!fs->partition->device_write(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
00764             return 0;
00765     }
00766     else
00767 #endif
00768     {
00769         uint16_t fat_entry = HTOL16(FAT16_CLUSTER_LAST_MAX);
00770         if(!fs->partition->device_write(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
00771             return 0;
00772     }
00773 
00774     /* free remaining clusters */
00775     if(cluster_num_next)
00776         return fat_free_clusters(fs, cluster_num_next);
00777     else
00778         return 1;
00779 }

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t fat_write_dir_entry ( const struct fat_fs_struct fs,
struct fat_dir_entry_struct dir_entry 
) [static]

Writes a directory entry to disk.

Note:
The file name is not checked for invalid characters.

The generation of the short 8.3 file name is quite simple. The first eight characters are used for the filename. The extension, if any, is made up of the first three characters following the last dot within the long filename. If the filename (without the extension) is longer than eight characters, the lower byte of the cluster number replaces the last two characters to avoid name clashes. In any other case, it is your responsibility to avoid name clashes.

Parameters:
[in] fs The filesystem on which to operate.
[in] dir_entry The directory entry to write.
Returns:
0 on failure, 1 on success.

Definition at line 1858 of file fat.c.

References fat_dir_entry_struct::attributes, fat_dir_entry_struct::cluster, partition_struct::device_write, fat_dir_entry_struct::entry_offset, fat_calc_83_checksum(), FAT_DIRENTRY_DELETED, FAT_DIRENTRY_LFNLAST, fat_get_datetime, fat_dir_entry_struct::file_size, htol16(), htol32(), fat_dir_entry_struct::long_name, min, and fat_fs_struct::partition.

Referenced by fat_close_file(), fat_create_dir(), fat_create_file(), fat_resize_file(), and fat_write_file().

01859 {
01860     if(!fs || !dir_entry)
01861         return 0;
01862     
01863 #if FAT_DATETIME_SUPPORT
01864     {
01865         uint16_t year;
01866         uint8_t month;
01867         uint8_t day;
01868         uint8_t hour;
01869         uint8_t min;
01870         uint8_t sec;
01871 
01872         fat_get_datetime(&year, &month, &day, &hour, &min, &sec);
01873         fat_set_file_modification_date(dir_entry, year, month, day);
01874         fat_set_file_modification_time(dir_entry, hour, min, sec);
01875     }
01876 #endif
01877 
01878     device_write_t device_write = fs->partition->device_write;
01879     offset_t offset = dir_entry->entry_offset;
01880     const char* name = dir_entry->long_name;
01881     uint8_t name_len = strlen(name);
01882 #if FAT_LFN_SUPPORT
01883     uint8_t lfn_entry_count = (name_len + 12) / 13;
01884 #endif
01885     uint8_t buffer[32];
01886 
01887     /* write 8.3 entry */
01888 
01889     /* generate 8.3 file name */
01890     memset(&buffer[0], ' ', 11);
01891     char* name_ext = strrchr(name, '.');
01892     if(name_ext && *++name_ext)
01893     {
01894         uint8_t name_ext_len = strlen(name_ext);
01895         name_len -= name_ext_len + 1;
01896 
01897         if(name_ext_len > 3)
01898 #if FAT_LFN_SUPPORT
01899             name_ext_len = 3;
01900 #else
01901             return 0;
01902 #endif
01903         
01904         memcpy(&buffer[8], name_ext, name_ext_len);
01905     }
01906     
01907     if(name_len <= 8)
01908     {
01909         memcpy(buffer, name, name_len);
01910 
01911 #if FAT_LFN_SUPPORT
01912         /* For now, we create lfn entries for all files,
01913          * except the "." and ".." directory references.
01914          * This is to avoid difficulties with capitalization,
01915          * as 8.3 filenames allow uppercase letters only.
01916          *
01917          * Theoretically it would be possible to leave
01918          * the 8.3 entry alone if the basename and the
01919          * extension have no mixed capitalization.
01920          */
01921         if(name[0] == '.' &&
01922            ((name[1] == '.' && name[2] == '\0') ||
01923             name[1] == '\0')
01924           )
01925             lfn_entry_count = 0;
01926 #endif
01927     }
01928     else
01929     {
01930 #if FAT_LFN_SUPPORT
01931         memcpy(buffer, name, 8);
01932 
01933         /* Minimize 8.3 name clashes by appending
01934          * the lower byte of the cluster number.
01935          */
01936         uint8_t num = dir_entry->cluster & 0xff;
01937 
01938         buffer[6] = (num < 0xa0) ? ('0' + (num >> 4)) : ('a' + (num >> 4));
01939         num &= 0x0f;
01940         buffer[7] = (num < 0x0a) ? ('0' + num) : ('a' + num);
01941 #else
01942         return 0;
01943 #endif
01944     }
01945     if(buffer[0] == FAT_DIRENTRY_DELETED)
01946         buffer[0] = 0x05;
01947 
01948     /* fill directory entry buffer */
01949     memset(&buffer[11], 0, sizeof(buffer) - 11);
01950     buffer[0x0b] = dir_entry->attributes;
01951 #if FAT_DATETIME_SUPPORT
01952     *((uint16_t*) &buffer[0x16]) = htol16(dir_entry->modification_time);
01953     *((uint16_t*) &buffer[0x18]) = htol16(dir_entry->modification_date);
01954 #endif
01955 #if FAT_FAT32_SUPPORT
01956     *((uint16_t*) &buffer[0x14]) = htol16((uint16_t) (dir_entry->cluster >> 16));
01957 #endif
01958     *((uint16_t*) &buffer[0x1a]) = htol16(dir_entry->cluster);
01959     *((uint32_t*) &buffer[0x1c]) = htol32(dir_entry->file_size);
01960 
01961     /* write to disk */
01962 #if FAT_LFN_SUPPORT
01963     if(!device_write(offset + (uint16_t) lfn_entry_count * 32, buffer, sizeof(buffer)))
01964 #else
01965     if(!device_write(offset, buffer, sizeof(buffer)))
01966 #endif
01967         return 0;
01968     
01969 #if FAT_LFN_SUPPORT
01970     /* calculate checksum of 8.3 name */
01971     uint8_t checksum = fat_calc_83_checksum(buffer);
01972     
01973     /* write lfn entries */
01974     uint8_t lfn_entry =0;
01975     for( lfn_entry = lfn_entry_count; lfn_entry > 0; --lfn_entry)
01976     {
01977         memset(buffer, 0xff, sizeof(buffer));
01978         
01979         /* set file name */
01980         const char* long_name_curr = name + (lfn_entry - 1) * 13;
01981         uint8_t i = 1;
01982         while(i < 0x1f)
01983         {
01984             buffer[i++] = *long_name_curr;
01985             buffer[i++] = 0;
01986 
01987             switch(i)
01988             {
01989                 case 0x0b:
01990                     i = 0x0e;
01991                     break;
01992                 case 0x1a:
01993                     i = 0x1c;
01994                     break;
01995             }
01996 
01997             if(!*long_name_curr++)
01998                 break;
01999         }
02000         
02001         /* set index of lfn entry */
02002         buffer[0x00] = lfn_entry;
02003         if(lfn_entry == lfn_entry_count)
02004             buffer[0x00] |= FAT_DIRENTRY_LFNLAST;
02005 
02006         /* mark as lfn entry */
02007         buffer[0x0b] = 0x0f;
02008 
02009         /* set 8.3 checksum */
02010         buffer[0x0d] = checksum;
02011 
02012         /* clear reserved bytes */
02013         buffer[0x0c] = 0;
02014         buffer[0x1a] = 0;
02015         buffer[0x1b] = 0;
02016 
02017         /* write entry */
02018         device_write(offset, buffer, sizeof(buffer));
02019     
02020         offset += sizeof(buffer);
02021     }
02022 #endif
02023     
02024     return 1;
02025 }

Here is the call graph for this function:

Here is the caller graph for this function:


Generated on Tue Jul 20 09:30:59 2010 for WaspmoteAPI by  doxygen 1.5.6