⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 AVR 单片机上实现SD卡的读写
💻 C
📖 第 1 页 / 共 5 页
字号:
#if FAT_FAT32_SUPPORT    if(fs->partition->type == PARTITION_TYPE_FAT32)    {        /* read appropriate fat entry */        uint32_t fat_entry;        if(!fs->partition->device_read(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))            return 0;        /* determine next cluster from fat */        cluster_num = ltoh32(fat_entry);                if(cluster_num == FAT32_CLUSTER_FREE ||           cluster_num == FAT32_CLUSTER_BAD ||           (cluster_num >= FAT32_CLUSTER_RESERVED_MIN && cluster_num <= FAT32_CLUSTER_RESERVED_MAX) ||           (cluster_num >= FAT32_CLUSTER_LAST_MIN && cluster_num <= FAT32_CLUSTER_LAST_MAX))            return 0;    }    else#endif    {        /* read appropriate fat entry */        uint16_t fat_entry;        if(!fs->partition->device_read(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))            return 0;        /* determine next cluster from fat */        cluster_num = ltoh16(fat_entry);                if(cluster_num == FAT16_CLUSTER_FREE ||           cluster_num == FAT16_CLUSTER_BAD ||           (cluster_num >= FAT16_CLUSTER_RESERVED_MIN && cluster_num <= FAT16_CLUSTER_RESERVED_MAX) ||           (cluster_num >= FAT16_CLUSTER_LAST_MIN && cluster_num <= FAT16_CLUSTER_LAST_MAX))            return 0;    }    return cluster_num;}#if DOXYGEN || FAT_WRITE_SUPPORT/** * \ingroup fat_fs * Appends a new cluster chain to an existing one. * * Set cluster_num to zero to create a completely new one. * * \param[in] fs The file system on which to operate. * \param[in] cluster_num The cluster to which to append the new chain. * \param[in] count The number of clusters to allocate. * \returns 0 on failure, the number of the first new cluster on success. */cluster_t fat_append_clusters(const struct fat_fs_struct* fs, cluster_t cluster_num, cluster_t count){    if(!fs)        return 0;    device_read_t device_read = fs->partition->device_read;    device_write_t device_write = fs->partition->device_write;    offset_t fat_offset = fs->header.fat_offset;    cluster_t count_left = count;    cluster_t cluster_next = 0;    cluster_t cluster_max;    uint16_t fat_entry16;#if FAT_FAT32_SUPPORT    uint32_t fat_entry32;    uint8_t is_fat32 = (fs->partition->type == PARTITION_TYPE_FAT32);    if(is_fat32)        cluster_max = fs->header.fat_size / sizeof(fat_entry32);    else#endif        cluster_max = fs->header.fat_size / sizeof(fat_entry16);    for(cluster_t cluster_new = 2; cluster_new < cluster_max; ++cluster_new)    {#if FAT_FAT32_SUPPORT        if(is_fat32)        {            if(!device_read(fat_offset + cluster_new * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32)))                return 0;        }        else#endif        {            if(!device_read(fat_offset + cluster_new * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16)))                return 0;        }#if FAT_FAT32_SUPPORT        if(is_fat32)        {            /* check if this is a free cluster */            if(fat_entry32 != HTOL32(FAT32_CLUSTER_FREE))                continue;            /* allocate cluster */            if(cluster_next == 0)                fat_entry32 = HTOL32(FAT32_CLUSTER_LAST_MAX);            else                fat_entry32 = htol32(cluster_next);            if(!device_write(fat_offset + cluster_new * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32)))                break;        }        else#endif        {            /* check if this is a free cluster */            if(fat_entry16 != HTOL16(FAT16_CLUSTER_FREE))                continue;            /* allocate cluster */            if(cluster_next == 0)                fat_entry16 = HTOL16(FAT16_CLUSTER_LAST_MAX);            else                fat_entry16 = htol16((uint16_t) cluster_next);            if(!device_write(fat_offset + cluster_new * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16)))                break;        }        cluster_next = cluster_new;        if(--count_left == 0)            break;    }    do    {        if(count_left > 0)            break;        /* We allocated a new cluster chain. Now join         * it with the existing one (if any).         */        if(cluster_num >= 2)        {#if FAT_FAT32_SUPPORT            if(is_fat32)            {                fat_entry32 = htol32(cluster_next);                if(!device_write(fat_offset + cluster_num * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32)))                    break;            }            else#endif            {                fat_entry16 = htol16((uint16_t) cluster_next);                if(!device_write(fat_offset + cluster_num * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16)))                    break;            }        }        return cluster_next;    } while(0);    /* No space left on device or writing error.     * Free up all clusters already allocated.     */    fat_free_clusters(fs, cluster_next);    return 0;}#endif#if DOXYGEN || FAT_WRITE_SUPPORT/** * \ingroup fat_fs * 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. * * \param[in] fs The filesystem on which to operate. * \param[in] cluster_num The starting cluster of the chain which to free. * \returns 0 on failure, 1 on success. * \see fat_terminate_clusters */uint8_t fat_free_clusters(const struct fat_fs_struct* fs, cluster_t cluster_num){    if(!fs || cluster_num < 2)        return 0;    offset_t fat_offset = fs->header.fat_offset;#if FAT_FAT32_SUPPORT    if(fs->partition->type == PARTITION_TYPE_FAT32)    {        uint32_t fat_entry;        while(cluster_num)        {            if(!fs->partition->device_read(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))                return 0;            /* get next cluster of current cluster before freeing current cluster */            uint32_t cluster_num_next = ltoh32(fat_entry);            if(cluster_num_next == FAT32_CLUSTER_FREE)                return 1;            if(cluster_num_next == FAT32_CLUSTER_BAD ||               (cluster_num_next >= FAT32_CLUSTER_RESERVED_MIN &&                cluster_num_next <= FAT32_CLUSTER_RESERVED_MAX               )              )                return 0;            if(cluster_num_next >= FAT32_CLUSTER_LAST_MIN && cluster_num_next <= FAT32_CLUSTER_LAST_MAX)                cluster_num_next = 0;            /* free cluster */            fat_entry = HTOL32(FAT32_CLUSTER_FREE);            fs->partition->device_write(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry));            /* We continue in any case here, even if freeing the cluster failed.             * The cluster is lost, but maybe we can still free up some later ones.             */            cluster_num = cluster_num_next;        }    }    else#endif    {        uint16_t fat_entry;        while(cluster_num)        {            if(!fs->partition->device_read(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))                return 0;            /* get next cluster of current cluster before freeing current cluster */            uint16_t cluster_num_next = ltoh16(fat_entry);            if(cluster_num_next == FAT16_CLUSTER_FREE)                return 1;            if(cluster_num_next == FAT16_CLUSTER_BAD ||               (cluster_num_next >= FAT16_CLUSTER_RESERVED_MIN &&                cluster_num_next <= FAT16_CLUSTER_RESERVED_MAX               )              )                return 0;            if(cluster_num_next >= FAT16_CLUSTER_LAST_MIN && cluster_num_next <= FAT16_CLUSTER_LAST_MAX)                cluster_num_next = 0;            /* free cluster */            fat_entry = HTOL16(FAT16_CLUSTER_FREE);            fs->partition->device_write(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry));            /* We continue in any case here, even if freeing the cluster failed.             * The cluster is lost, but maybe we can still free up some later ones.             */            cluster_num = cluster_num_next;        }    }    return 1;}#endif#if DOXYGEN || FAT_WRITE_SUPPORT/** * \ingroup fat_fs * 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. * * \param[in] fs The filesystem on which to operate. * \param[in] cluster_num The new end of the cluster chain. * \returns 0 on failure, 1 on success. * \see fat_free_clusters */uint8_t fat_terminate_clusters(const struct fat_fs_struct* fs, cluster_t cluster_num){    if(!fs || cluster_num < 2)        return 0;    /* fetch next cluster before overwriting the cluster entry */    cluster_t cluster_num_next = fat_get_next_cluster(fs, cluster_num);    /* mark cluster as the last one */#if FAT_FAT32_SUPPORT    if(fs->partition->type == PARTITION_TYPE_FAT32)    {        uint32_t fat_entry = HTOL32(FAT32_CLUSTER_LAST_MAX);        if(!fs->partition->device_write(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))            return 0;    }    else#endif    {        uint16_t fat_entry = HTOL16(FAT16_CLUSTER_LAST_MAX);        if(!fs->partition->device_write(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))            return 0;    }    /* free remaining clusters */    if(cluster_num_next)        return fat_free_clusters(fs, cluster_num_next);    else        return 1;}#endif#if DOXYGEN || FAT_WRITE_SUPPORT/** * \ingroup fat_fs * Clears a single cluster. * * The complete cluster is filled with zeros. * * \param[in] fs The filesystem on which to operate. * \param[in] cluster_num The cluster to clear. * \returns 0 on failure, 1 on success. */uint8_t fat_clear_cluster(const struct fat_fs_struct* fs, cluster_t cluster_num){    if(cluster_num < 2)        return 0;    offset_t cluster_offset = fat_cluster_offset(fs, cluster_num);    uint8_t zero[16];    memset(zero, 0, sizeof(zero));    return fs->partition->device_write_interval(cluster_offset,                                                zero,                                                fs->header.cluster_size,                                                fat_clear_cluster_callback,                                                0                                               );}#endif#if DOXYGEN || FAT_WRITE_SUPPORT/** * \ingroup fat_fs * Callback function for clearing a cluster. */uintptr_t fat_clear_cluster_callback(uint8_t* buffer, offset_t offset, void* p){    return 16;}#endif/** * \ingroup fat_fs * Calculates the offset of the specified cluster. * * \param[in] fs The filesystem on which to operate. * \param[in] cluster_num The cluster whose offset to calculate. * \returns The cluster offset. */offset_t fat_cluster_offset(const struct fat_fs_struct* fs, cluster_t cluster_num){    if(!fs || cluster_num < 2)        return 0;    return fs->header.cluster_zero_offset + (offset_t) (cluster_num - 2) * fs->header.cluster_size;}/** * \ingroup fat_file * Retrieves the directory entry of a path. * * The given path may both describe a file or a directory. * * \param[in] fs The FAT filesystem on which to search. * \param[in] path The path of which to read the directory entry. * \param[out] dir_entry The directory entry to fill. * \returns 0 on failure, 1 on success. * \see fat_read_dir */uint8_t fat_get_dir_entry_of_path(struct fat_fs_struct* fs, const char* path, struct fat_dir_entry_struct* dir_entry){    if(!fs || !path || path[0] == '\0' || !dir_entry)        return 0;    if(path[0] == '/')        ++path;    /* begin with the root directory */    memset(dir_entry, 0, sizeof(*dir_entry));    dir_entry->attributes = FAT_ATTRIB_DIR;    while(1)    {        if(path[0] == '\0')            return 1;        struct fat_dir_struct* dd = fat_open_dir(fs, dir_entry);        if(!dd)            break;        /* extract the next hierarchy we will search for */        const char* sub_path = strchr(path, '/');        uint8_t length_to_sep;        if(sub_path)        {            length_to_sep = sub_path - path;            ++sub_path;        }        else        {            length_to_sep = strlen(path);            sub_path = path + length_to_sep;        }                /* read directory entries */        while(fat_read_dir(dd, dir_entry))        {            /* check if we have found the next hierarchy */            if((strlen(dir_entry->long_name) != length_to_sep ||                strncmp(path, dir_entry->long_name, length_to_sep) != 0))                continue;            fat_close_dir(dd);            dd = 0;            if(path[length_to_sep] == '\0')                /* we iterated through the whole path and have found the file */                return 1;            if(dir_entry->attributes & FAT_ATTRIB_DIR)            {                /* we found a parent directory of the file we are searching for */                path = sub_path;                break;            }            /* a parent of the file exists, but not the file itself */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -