FAT file functions
[FAT support]

Collaboration diagram for FAT file functions:

Data Structures

struct  fat_dir_entry_struct

Defines

#define FAT_ATTRIB_READONLY   (1 << 0)
#define FAT_ATTRIB_HIDDEN   (1 << 1)
#define FAT_ATTRIB_SYSTEM   (1 << 2)
#define FAT_ATTRIB_VOLUME   (1 << 3)
#define FAT_ATTRIB_DIR   (1 << 4)
#define FAT_ATTRIB_ARCHIVE   (1 << 5)
#define FAT_SEEK_SET   0
#define FAT_SEEK_CUR   1
#define FAT_SEEK_END   2

Functions

uint8_t fat_get_dir_entry_of_path (struct fat_fs_struct *fs, const char *path, struct fat_dir_entry_struct *dir_entry)
struct fat_file_structfat_open_file (struct fat_fs_struct *fs, const struct fat_dir_entry_struct *dir_entry)
void fat_close_file (struct fat_file_struct *fd)
intptr_t fat_read_file (struct fat_file_struct *fd, uint8_t *buffer, uintptr_t buffer_len)
intptr_t fat_write_file (struct fat_file_struct *fd, const uint8_t *buffer, uintptr_t buffer_len)
uint8_t fat_seek_file (struct fat_file_struct *fd, int32_t *offset, uint8_t whence)
uint8_t fat_resize_file (struct fat_file_struct *fd, uint32_t size)
uint8_t fat_create_file (struct fat_dir_struct *parent, const char *file, struct fat_dir_entry_struct *dir_entry)
uint8_t fat_delete_file (struct fat_fs_struct *fs, struct fat_dir_entry_struct *dir_entry)

Detailed Description

Functions for managing files.

Define Documentation

#define FAT_ATTRIB_ARCHIVE   (1 << 5)

The file has to be archived.

Definition at line 50 of file fat.h.

#define FAT_ATTRIB_DIR   (1 << 4)

#define FAT_ATTRIB_HIDDEN   (1 << 1)

The file is hidden.

Definition at line 42 of file fat.h.

#define FAT_ATTRIB_READONLY   (1 << 0)

The file is read-only.

Definition at line 40 of file fat.h.

Referenced by WaspSD::getAttributes(), and WaspSD::ls().

#define FAT_ATTRIB_SYSTEM   (1 << 2)

The file is a system file.

Definition at line 44 of file fat.h.

#define FAT_ATTRIB_VOLUME   (1 << 3)

The file is empty and has the volume label as its name.

Definition at line 46 of file fat.h.

#define FAT_SEEK_CUR   1

The given offset is relative to the current read/write position.

Definition at line 55 of file fat.h.

Referenced by fat_seek_file().

#define FAT_SEEK_END   2

The given offset is relative to the end of the file.

Definition at line 57 of file fat.h.

Referenced by fat_seek_file().

#define FAT_SEEK_SET   0

The given offset is relative to the beginning of the file.

Definition at line 53 of file fat.h.

Referenced by WaspSD::cat(), WaspSD::catBin(), fat_seek_file(), and WaspSD::writeSD().


Function Documentation

void fat_close_file ( struct fat_file_struct fd  ) 

Closes a file.

Parameters:
[in] fd The file handle of the file to close.
See also:
fat_open_file

Definition at line 964 of file fat.c.

References fat_file_struct::dir_entry, fat_write_dir_entry(), and fat_file_struct::fs.

Referenced by WaspSD::cat(), WaspSD::catBin(), WaspSD::catln(), WaspSD::closeFile(), WaspSD::indexOf(), WaspSD::numln(), and WaspSD::writeSD().

00965 {
00966     if(fd)
00967     {
00968 #if FAT_DELAY_DIRENTRY_UPDATE
00969         /* write directory entry */
00970         fat_write_dir_entry(fd->fs, &fd->dir_entry);
00971 #endif
00972 
00973 #if USE_DYNAMIC_MEMORY
00974         free(fd);
00975 #else
00976         fd->fs = 0;
00977 #endif
00978     }
00979 }

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t fat_create_file ( struct fat_dir_struct parent,
const char *  file,
struct fat_dir_entry_struct dir_entry 
)

Creates a file.

Creates a file and obtains the directory entry of the new file. If the file to create already exists, the directory entry of the existing file will be returned within the dir_entry parameter.

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] parent The handle of the directory in which to create the file.
[in] file The name of the file to create.
[out] dir_entry The directory entry to fill for the new file.
Returns:
0 on failure, 1 on success.
See also:
fat_delete_file

Definition at line 2055 of file fat.c.

References fat_dir_entry_struct::entry_offset, fat_find_offset_for_dir_entry(), fat_read_dir(), fat_reset_dir(), fat_write_dir_entry(), fat_dir_struct::fs, and fat_dir_entry_struct::long_name.

Referenced by WaspSD::create().

02056 {
02057     if(!parent || !file || !file[0] || !dir_entry)
02058         return 0;
02059 
02060     /* check if the file already exists */
02061     while(1)
02062     {
02063         if(!fat_read_dir(parent, dir_entry))
02064             break;
02065 
02066         if(strcmp(file, dir_entry->long_name) == 0)
02067         {
02068             fat_reset_dir(parent);
02069             return 0;
02070         }
02071     }
02072 
02073     struct fat_fs_struct* fs = parent->fs;
02074 
02075     /* prepare directory entry with values already known */
02076     memset(dir_entry, 0, sizeof(*dir_entry));
02077     strncpy(dir_entry->long_name, file, sizeof(dir_entry->long_name) - 1);
02078 
02079     /* find place where to store directory entry */
02080     if(!(dir_entry->entry_offset = fat_find_offset_for_dir_entry(fs, parent, dir_entry)))
02081         return 0;
02082     
02083     /* write directory entry to disk */
02084     if(!fat_write_dir_entry(fs, dir_entry))
02085         return 0;
02086     
02087     return 1;
02088 }

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t fat_delete_file ( struct fat_fs_struct fs,
struct fat_dir_entry_struct dir_entry 
)

Deletes a file or directory.

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 file to delete.
Returns:
0 on failure, 1 on success.
See also:
fat_create_file

Definition at line 2106 of file fat.c.

References fat_dir_entry_struct::cluster, partition_struct::device_read, partition_struct::device_write, fat_dir_entry_struct::entry_offset, FAT_DIRENTRY_DELETED, fat_free_clusters(), and fat_fs_struct::partition.

Referenced by WaspSD::delDir(), and WaspSD::delFile().

02107 {
02108     if(!fs || !dir_entry)
02109         return 0;
02110 
02111     /* get offset of the file's directory entry */
02112     offset_t dir_entry_offset = dir_entry->entry_offset;
02113     if(!dir_entry_offset)
02114         return 0;
02115 
02116 #if FAT_LFN_SUPPORT
02117     uint8_t buffer[12];
02118     while(1)
02119     {
02120         /* read directory entry */
02121         if(!fs->partition->device_read(dir_entry_offset, buffer, sizeof(buffer)))
02122             return 0;
02123         
02124         /* mark the directory entry as deleted */
02125         buffer[0] = FAT_DIRENTRY_DELETED;
02126         
02127         /* write back entry */
02128         if(!fs->partition->device_write(dir_entry_offset, buffer, sizeof(buffer)))
02129             return 0;
02130 
02131         /* check if we deleted the whole entry */
02132         if(buffer[11] != 0x0f)
02133             break;
02134 
02135         dir_entry_offset += 32;
02136     }
02137 #else
02138     /* mark the directory entry as deleted */
02139     uint8_t first_char = FAT_DIRENTRY_DELETED;
02140     if(!fs->partition->device_write(dir_entry_offset, &first_char, 1))
02141         return 0;
02142 #endif
02143 
02144     /* We deleted the directory entry. The next thing to do is
02145      * marking all occupied clusters as free.
02146      */
02147     return (dir_entry->cluster == 0 || fat_free_clusters(fs, dir_entry->cluster));
02148 }

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t fat_get_dir_entry_of_path ( struct fat_fs_struct fs,
const char *  path,
struct fat_dir_entry_struct dir_entry 
)

Retrieves the directory entry of a path.

The given path may both describe a file or a directory.

Parameters:
[in] fs The FAT filesystem on which to search.
[in] path The path of which to read the directory entry.
[out] dir_entry The directory entry to fill.
Returns:
0 on failure, 1 on success.
See also:
fat_read_dir

Definition at line 850 of file fat.c.

References fat_dir_entry_struct::attributes, FAT_ATTRIB_DIR, fat_close_dir(), fat_open_dir(), fat_read_dir(), and fat_dir_entry_struct::long_name.

Referenced by WaspSD::init().

00851 {
00852     if(!fs || !path || path[0] == '\0' || !dir_entry)
00853         return 0;
00854 
00855     if(path[0] == '/')
00856         ++path;
00857 
00858     /* begin with the root directory */
00859     memset(dir_entry, 0, sizeof(*dir_entry));
00860     dir_entry->attributes = FAT_ATTRIB_DIR;
00861 
00862     while(1)
00863     {
00864         if(path[0] == '\0')
00865             return 1;
00866 
00867         struct fat_dir_struct* dd = fat_open_dir(fs, dir_entry);
00868         if(!dd)
00869             break;
00870 
00871         /* extract the next hierarchy we will search for */
00872         const char* sub_path = strchr(path, '/');
00873         uint8_t length_to_sep;
00874         if(sub_path)
00875         {
00876             length_to_sep = sub_path - path;
00877             ++sub_path;
00878         }
00879         else
00880         {
00881             length_to_sep = strlen(path);
00882             sub_path = path + length_to_sep;
00883         }
00884         
00885         /* read directory entries */
00886         while(fat_read_dir(dd, dir_entry))
00887         {
00888             /* check if we have found the next hierarchy */
00889             if((strlen(dir_entry->long_name) != length_to_sep ||
00890                 strncmp(path, dir_entry->long_name, length_to_sep) != 0))
00891                 continue;
00892 
00893             fat_close_dir(dd);
00894             dd = 0;
00895 
00896             if(path[length_to_sep] == '\0')
00897                 /* we iterated through the whole path and have found the file */
00898                 return 1;
00899 
00900             if(dir_entry->attributes & FAT_ATTRIB_DIR)
00901             {
00902                 /* we found a parent directory of the file we are searching for */
00903                 path = sub_path;
00904                 break;
00905             }
00906 
00907             /* a parent of the file exists, but not the file itself */
00908             return 0;
00909         }
00910 
00911         fat_close_dir(dd);
00912     }
00913     
00914     return 0;
00915 }

Here is the call graph for this function:

Here is the caller graph for this function:

struct fat_file_struct* fat_open_file ( struct fat_fs_struct fs,
const struct fat_dir_entry_struct dir_entry 
) [read]

Opens a file on a FAT filesystem.

Parameters:
[in] fs The filesystem on which the file to open lies.
[in] dir_entry The directory entry of the file to open.
Returns:
The file handle, or 0 on failure.
See also:
fat_close_file

Definition at line 926 of file fat.c.

References fat_dir_entry_struct::attributes, fat_dir_entry_struct::cluster, fat_file_struct::dir_entry, FAT_ATTRIB_DIR, FAT_FILE_COUNT, fat_file_handles, fat_file_struct::fs, fat_file_struct::pos, and fat_file_struct::pos_cluster.

Referenced by WaspSD::openFile().

00927 {
00928     if(!fs || !dir_entry || (dir_entry->attributes & FAT_ATTRIB_DIR))
00929         return 0;
00930 
00931 #if USE_DYNAMIC_MEMORY
00932     struct fat_file_struct* fd = malloc(sizeof(*fd));
00933     if(!fd)
00934         return 0;
00935 #else
00936     struct fat_file_struct* fd = fat_file_handles;
00937     uint8_t i;
00938     for(i = 0; i < FAT_FILE_COUNT; ++i)
00939     {
00940         if(!fd->fs)
00941             break;
00942 
00943         ++fd;
00944     }
00945     if(i >= FAT_FILE_COUNT)
00946         return 0;
00947 #endif
00948     
00949     memcpy(&fd->dir_entry, dir_entry, sizeof(*dir_entry));
00950     fd->fs = fs;
00951     fd->pos = 0;
00952     fd->pos_cluster = dir_entry->cluster;
00953 
00954     return fd;
00955 }

Here is the caller graph for this function:

intptr_t fat_read_file ( struct fat_file_struct fd,
uint8_t *  buffer,
uintptr_t  buffer_len 
)

Reads data from a file.

The data requested is read from the current file location.

Parameters:
[in] fd The file handle of the file from which to read.
[out] buffer The buffer into which to write.
[in] buffer_len The amount of data to read.
Returns:
The number of bytes read, 0 on end of file, or -1 on failure.
See also:
fat_write_file

Definition at line 993 of file fat.c.

References fat_dir_entry_struct::cluster, fat_header_struct::cluster_size, partition_struct::device_read, fat_file_struct::dir_entry, fat_cluster_offset(), fat_get_next_cluster(), fat_dir_entry_struct::file_size, fat_file_struct::fs, fat_fs_struct::header, fat_fs_struct::partition, fat_file_struct::pos, and fat_file_struct::pos_cluster.

Referenced by WaspSD::cat(), WaspSD::catBin(), WaspSD::catln(), WaspSD::indexOf(), and WaspSD::numln().

00994 {
00995     /* check arguments */
00996     if(!fd || !buffer || buffer_len < 1)
00997         return -1;
00998 
00999     /* determine number of bytes to read */
01000     if(fd->pos + buffer_len > fd->dir_entry.file_size)
01001         buffer_len = fd->dir_entry.file_size - fd->pos;
01002     if(buffer_len == 0)
01003         return 0;
01004     
01005     uint16_t cluster_size = fd->fs->header.cluster_size;
01006     cluster_t cluster_num = fd->pos_cluster;
01007     uintptr_t buffer_left = buffer_len;
01008     uint16_t first_cluster_offset = (uint16_t) (fd->pos & (cluster_size - 1));
01009 
01010     /* find cluster in which to start reading */
01011     if(!cluster_num)
01012     {
01013         cluster_num = fd->dir_entry.cluster;
01014         
01015         if(!cluster_num)
01016         {
01017             if(!fd->pos)
01018                 return 0;
01019             else
01020                 return -1;
01021         }
01022 
01023         if(fd->pos)
01024         {
01025             uint32_t pos = fd->pos;
01026             while(pos >= cluster_size)
01027             {
01028                 pos -= cluster_size;
01029                 cluster_num = fat_get_next_cluster(fd->fs, cluster_num);
01030                 if(!cluster_num)
01031                     return -1;
01032             }
01033         }
01034     }
01035     
01036     /* read data */
01037     do
01038     {
01039         /* calculate data size to copy from cluster */
01040         offset_t cluster_offset = fat_cluster_offset(fd->fs, cluster_num) + first_cluster_offset;
01041         uint16_t copy_length = cluster_size - first_cluster_offset;
01042         if(copy_length > buffer_left)
01043             copy_length = buffer_left;
01044 
01045         /* read data */
01046         if(!fd->fs->partition->device_read(cluster_offset, buffer, copy_length))
01047             return buffer_len - buffer_left;
01048 
01049         /* calculate new file position */
01050         buffer += copy_length;
01051         buffer_left -= copy_length;
01052         fd->pos += copy_length;
01053 
01054         if(first_cluster_offset + copy_length >= cluster_size)
01055         {
01056             /* we are on a cluster boundary, so get the next cluster */
01057             if((cluster_num = fat_get_next_cluster(fd->fs, cluster_num)))
01058             {
01059                 first_cluster_offset = 0;
01060             }
01061             else
01062             {
01063                 fd->pos_cluster = 0;
01064                 return buffer_len - buffer_left;
01065             }
01066         }
01067 
01068         fd->pos_cluster = cluster_num;
01069 
01070     } while(buffer_left > 0); /* check if we are done */
01071 
01072     return buffer_len;
01073 }

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t fat_resize_file ( struct fat_file_struct fd,
uint32_t  size 
)

Resizes a file to have a specific size.

Enlarges or shrinks the file pointed to by the file descriptor to have exactly the specified size.

If the file is truncated, all bytes having an equal or larger offset than the given size are lost. If the file is expanded, the additional bytes are allocated.

Note:
Please be aware that this function just allocates or deallocates disk space, it does not explicitely clear it. To avoid data leakage, this must be done manually.
Parameters:
[in] fd The file decriptor of the file which to resize.
[in] size The new size of the file.
Returns:
0 on failure, 1 on success.

Definition at line 1288 of file fat.c.

References fat_dir_entry_struct::cluster, fat_header_struct::cluster_size, fat_file_struct::dir_entry, fat_append_clusters(), fat_free_clusters(), fat_get_next_cluster(), fat_terminate_clusters(), fat_write_dir_entry(), fat_dir_entry_struct::file_size, fat_file_struct::fs, fat_fs_struct::header, fat_file_struct::pos, and fat_file_struct::pos_cluster.

Referenced by fat_seek_file().

01289 {
01290     if(!fd)
01291         return 0;
01292 
01293     cluster_t cluster_num = fd->dir_entry.cluster;
01294     uint16_t cluster_size = fd->fs->header.cluster_size;
01295     uint32_t size_new = size;
01296 
01297     do
01298     {
01299         if(cluster_num == 0 && size_new == 0)
01300             /* the file stays empty */
01301             break;
01302 
01303         /* seek to the next cluster as long as we need the space */
01304         while(size_new > cluster_size)
01305         {
01306             /* get next cluster of file */
01307             cluster_t cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num);
01308             if(cluster_num_next)
01309             {
01310                 cluster_num = cluster_num_next;
01311                 size_new -= cluster_size;
01312             }
01313             else
01314             {
01315                 break;
01316             }
01317         }
01318 
01319         if(size_new > cluster_size || cluster_num == 0)
01320         {
01321             /* Allocate new cluster chain and append
01322              * it to the existing one, if available.
01323              */
01324             cluster_t cluster_count = (size_new + cluster_size - 1) / cluster_size;
01325             cluster_t cluster_new_chain = fat_append_clusters(fd->fs, cluster_num, cluster_count);
01326             if(!cluster_new_chain)
01327                 return 0;
01328 
01329             if(!cluster_num)
01330             {
01331                 cluster_num = cluster_new_chain;
01332                 fd->dir_entry.cluster = cluster_num;
01333             }
01334         }
01335 
01336         /* write new directory entry */
01337         fd->dir_entry.file_size = size;
01338         if(size == 0)
01339             fd->dir_entry.cluster = 0;
01340         if(!fat_write_dir_entry(fd->fs, &fd->dir_entry))
01341             return 0;
01342 
01343         if(size == 0)
01344         {
01345             /* free all clusters of file */
01346             fat_free_clusters(fd->fs, cluster_num);
01347         }
01348         else if(size_new <= cluster_size)
01349         {
01350             /* free all clusters no longer needed */
01351             fat_terminate_clusters(fd->fs, cluster_num);
01352         }
01353 
01354     } while(0);
01355 
01356     /* correct file position */
01357     if(size < fd->pos)
01358     {
01359         fd->pos = size;
01360         fd->pos_cluster = 0;
01361     }
01362 
01363     return 1;
01364 }

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t fat_seek_file ( struct fat_file_struct fd,
int32_t *  offset,
uint8_t  whence 
)

Repositions the read/write file offset.

Changes the file offset where the next call to fat_read_file() or fat_write_file() starts reading/writing.

If the new offset is beyond the end of the file, fat_resize_file() is implicitly called, i.e. the file is expanded.

The new offset can be given in different ways determined by the whence parameter:

  • FAT_SEEK_SET: *offset is relative to the beginning of the file.
  • FAT_SEEK_CUR: *offset is relative to the current file position.
  • FAT_SEEK_END: *offset is relative to the end of the file.

The resulting absolute offset is written to the location the offset parameter points to.

Parameters:
[in] fd The file decriptor of the file on which to seek.
[in,out] offset A pointer to the new offset, as affected by the whence parameter. The function writes the new absolute offset to this location before it returns.
[in] whence Affects the way offset is interpreted, see above.
Returns:
0 on failure, 1 on success.

Definition at line 1233 of file fat.c.

References fat_file_struct::dir_entry, fat_resize_file(), FAT_SEEK_CUR, FAT_SEEK_END, FAT_SEEK_SET, FAT_WRITE_SUPPORT, fat_dir_entry_struct::file_size, fat_file_struct::pos, and fat_file_struct::pos_cluster.

Referenced by WaspSD::cat(), WaspSD::catBin(), and WaspSD::writeSD().

01234 {
01235     if(!fd || !offset)
01236         return 0;
01237 
01238     uint32_t new_pos = fd->pos;
01239     switch(whence)
01240     {
01241         case FAT_SEEK_SET:
01242             new_pos = *offset;
01243             break;
01244         case FAT_SEEK_CUR:
01245             new_pos += *offset;
01246             break;
01247         case FAT_SEEK_END:
01248             new_pos = fd->dir_entry.file_size + *offset;
01249             break;
01250         default:
01251             return 0;
01252     }
01253 
01254     if(new_pos > fd->dir_entry.file_size
01255 #if FAT_WRITE_SUPPORT
01256        && !fat_resize_file(fd, new_pos)
01257 #endif
01258        )
01259         return 0;
01260 
01261     fd->pos = new_pos;
01262     fd->pos_cluster = 0;
01263 
01264     *offset = (int32_t) new_pos;
01265     return 1;
01266 }

Here is the call graph for this function:

Here is the caller graph for this function:

intptr_t fat_write_file ( struct fat_file_struct fd,
const uint8_t *  buffer,
uintptr_t  buffer_len 
)

Writes data to a file.

The data is written to the current file location.

Parameters:
[in] fd The file handle of the file to which to write.
[in] buffer The buffer from which to read the data to be written.
[in] buffer_len The amount of data to write.
Returns:
The number of bytes written, 0 on disk full, or -1 on failure.
See also:
fat_read_file

Definition at line 1088 of file fat.c.

References fat_dir_entry_struct::cluster, fat_header_struct::cluster_size, partition_struct::device_write, fat_file_struct::dir_entry, fat_append_clusters(), fat_cluster_offset(), fat_get_next_cluster(), fat_write_dir_entry(), fat_dir_entry_struct::file_size, fat_file_struct::fs, fat_fs_struct::header, fat_fs_struct::partition, fat_file_struct::pos, and fat_file_struct::pos_cluster.

Referenced by WaspSD::writeSD().

01089 {
01090     /* check arguments */
01091     if(!fd || !buffer || buffer_len < 1)
01092         return -1;
01093     if(fd->pos > fd->dir_entry.file_size)
01094         return -1;
01095 
01096     uint16_t cluster_size = fd->fs->header.cluster_size;
01097     cluster_t cluster_num = fd->pos_cluster;
01098     uintptr_t buffer_left = buffer_len;
01099     uint16_t first_cluster_offset = (uint16_t) (fd->pos & (cluster_size - 1));
01100 
01101     /* find cluster in which to start writing */
01102     if(!cluster_num)
01103     {
01104         cluster_num = fd->dir_entry.cluster;
01105         
01106         if(!cluster_num)
01107         {
01108             if(!fd->pos)
01109             {
01110                 /* empty file */
01111                 fd->dir_entry.cluster = cluster_num = fat_append_clusters(fd->fs, 0, 1);
01112                 if(!cluster_num)
01113                     return -1;
01114             }
01115             else
01116             {
01117                 return -1;
01118             }
01119         }
01120 
01121         if(fd->pos)
01122         {
01123             uint32_t pos = fd->pos;
01124             cluster_t cluster_num_next;
01125             while(pos >= cluster_size)
01126             {
01127                 pos -= cluster_size;
01128                 cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num);
01129                 if(!cluster_num_next && pos == 0)
01130                     /* the file exactly ends on a cluster boundary, and we append to it */
01131                     cluster_num_next = fat_append_clusters(fd->fs, cluster_num, 1);
01132                 if(!cluster_num_next)
01133                     return -1;
01134 
01135                 cluster_num = cluster_num_next;
01136             }
01137         }
01138     }
01139     
01140     /* write data */
01141     do
01142     {
01143         /* calculate data size to write to cluster */
01144         offset_t cluster_offset = fat_cluster_offset(fd->fs, cluster_num) + first_cluster_offset;
01145         uint16_t write_length = cluster_size - first_cluster_offset;
01146         if(write_length > buffer_left)
01147             write_length = buffer_left;
01148 
01149         /* write data which fits into the current cluster */
01150         if(!fd->fs->partition->device_write(cluster_offset, buffer, write_length))
01151             break;
01152 
01153         /* calculate new file position */
01154         buffer += write_length;
01155         buffer_left -= write_length;
01156         fd->pos += write_length;
01157 
01158         if(first_cluster_offset + write_length >= cluster_size)
01159         {
01160             /* we are on a cluster boundary, so get the next cluster */
01161             cluster_t cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num);
01162             if(!cluster_num_next && buffer_left > 0)
01163                 /* we reached the last cluster, append a new one */
01164                 cluster_num_next = fat_append_clusters(fd->fs, cluster_num, 1);
01165             if(!cluster_num_next)
01166             {
01167                 fd->pos_cluster = 0;
01168                 break;
01169             }
01170 
01171             cluster_num = cluster_num_next;
01172             first_cluster_offset = 0;
01173         }
01174 
01175         fd->pos_cluster = cluster_num;
01176 
01177     } while(buffer_left > 0); /* check if we are done */
01178 
01179     /* update directory entry */
01180     if(fd->pos > fd->dir_entry.file_size)
01181     {
01182 #if !FAT_DELAY_DIRENTRY_UPDATE
01183         uint32_t size_old = fd->dir_entry.file_size;
01184 #endif
01185 
01186         /* update file size */
01187         fd->dir_entry.file_size = fd->pos;
01188 
01189 #if !FAT_DELAY_DIRENTRY_UPDATE
01190         /* write directory entry */
01191         if(!fat_write_dir_entry(fd->fs, &fd->dir_entry))
01192         {
01193             /* We do not return an error here since we actually wrote
01194              * some data to disk. So we calculate the amount of data
01195              * we wrote to disk and which lies within the old file size.
01196              */
01197             buffer_left = fd->pos - size_old;
01198             fd->pos = size_old;
01199         }
01200 #endif
01201     }
01202 
01203     return buffer_len - buffer_left;
01204 }

Here is the call graph for this function:

Here is the caller graph for this function:


Generated on Tue Jul 20 09:31:00 2010 for WaspmoteAPI by  doxygen 1.5.6