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

📄 fat16.c

📁 包装了一个开源的FAT16文件系统
💻 C
📖 第 1 页 / 共 5 页
字号:
 * \param[in,out] dir_entry The directory entry to fill. * \param[in] raw_entry A pointer to 32 bytes of raw data. * \returns 0 on failure, 1 on success and 2 if the *          directory entry is complete. */uint8_t fat16_interpret_dir_entry(struct fat16_dir_entry_struct* dir_entry, const uint8_t* raw_entry){	char* long_name;
	uint16_t char_offset;
	uint8_t i,j;
    if(!dir_entry || !raw_entry || !raw_entry[0])        return 0;
	long_name = dir_entry->long_name;    if(raw_entry[11] == 0x0f)    {        char_offset = ((raw_entry[0] & 0x3f) - 1) * 13;        if(char_offset + 12 < sizeof(dir_entry->long_name))        {            /* Lfn supports unicode, but we do not, for now.             * So we assume pure ascii and read only every             * second byte.             */            long_name[char_offset + 0] = raw_entry[1];            long_name[char_offset + 1] = raw_entry[3];            long_name[char_offset + 2] = raw_entry[5];            long_name[char_offset + 3] = raw_entry[7];            long_name[char_offset + 4] = raw_entry[9];            long_name[char_offset + 5] = raw_entry[14];            long_name[char_offset + 6] = raw_entry[16];            long_name[char_offset + 7] = raw_entry[18];            long_name[char_offset + 8] = raw_entry[20];            long_name[char_offset + 9] = raw_entry[22];            long_name[char_offset + 10] = raw_entry[24];            long_name[char_offset + 11] = raw_entry[28];            long_name[char_offset + 12] = raw_entry[30];        }        return 1;    }    else    {        /* if we do not have a long name, take the short one */        if(long_name[0] == '\0')        {                        for(i = 0; i < 8; ++i)            {                if(raw_entry[i] == ' ')                    break;                long_name[i] = raw_entry[i];            }            if(long_name[0] == 0x05)                long_name[0] = (char) FAT16_DIRENTRY_DELETED;            if(raw_entry[8] != ' ')            {                long_name[i++] = '.';                j = 8;                for(; j < 11; ++j)                {                    if(raw_entry[j] != ' ')                    {                        long_name[i++] = raw_entry[j];                    }                    else                    {                        break;                    }                }            }             long_name[i] = '\0';        }                /* extract properties of file and store them within the structure */        dir_entry->attributes = raw_entry[11];        dir_entry->cluster = ((uint16_t) raw_entry[26]) |                             ((uint16_t) raw_entry[27] << 8);        dir_entry->file_size = ((uint32_t) raw_entry[28]) |                               ((uint32_t) raw_entry[29] << 8) |                               ((uint32_t) raw_entry[30] << 16) |                               ((uint32_t) raw_entry[31] << 24);#if FAT16_DATETIME_SUPPORT        dir_entry->modification_time = ((uint16_t) raw_entry[22]) |                                       ((uint16_t) raw_entry[23] << 8);        dir_entry->modification_date = ((uint16_t) raw_entry[24]) |                                       ((uint16_t) raw_entry[25] << 8);#endif        return 2;    }}/** * \ingroup fat16_file * Retrieves the directory entry of a path. * * The given path may both describe a file or a directory. * * \param[in] fs The FAT16 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 fat16_read_dir */uint8_t fat16_get_dir_entry_of_path(struct fat16_fs_struct* fs, const char* path, struct fat16_dir_entry_struct* dir_entry){
	char* sep_pos;
	struct fat16_dir_struct* dd;
	uint8_t length_to_sep;
    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 = FAT16_ATTRIB_DIR;    if(path[0] == '\0')        return 1;    while(1)    {        dd = fat16_open_dir(fs, dir_entry);        if(!dd)            break;        /* extract the next hierarchy we will search for */        sep_pos = strchr(path, '/');        if(!sep_pos)            sep_pos = (char *)path + strlen(path);        length_to_sep =(U8)( sep_pos - path);                /* read directory entries */        while(fat16_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;            fat16_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 & FAT16_ATTRIB_DIR)            {                /* we found a parent directory of the file we are searching for */                path = sep_pos + 1;                break;            }            /* a parent of the file exists, but not the file itself */            return 0;        }        fat16_close_dir(dd);    }        return 0;}/** * \ingroup fat16_fs * 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. * * \param[in] fs The filesystem for which to determine the next cluster. * \param[in] cluster_num The number of the cluster for which to determine its successor. * \returns The wanted cluster number, or 0 on error. */uint16_t fat16_get_next_cluster(const struct fat16_fs_struct* fs, uint16_t cluster_num){    uint8_t fat_entry[2];
	
	if(!fs || cluster_num < 2)        return 0;    /* read appropriate fat entry */        if(!fs->partition->device_read(fs->header.fat_offset + 2 * cluster_num, fat_entry, 2))        return 0;    /* determine next cluster from fat */    cluster_num = ((uint16_t) fat_entry[0]) |                  ((uint16_t) fat_entry[1] << 8);        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;}/** * \ingroup fat16_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. */uint16_t fat16_append_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num, uint16_t count){#if FAT16_WRITE_SUPPORT

    device_read_t device_read;    device_write_t device_write;    uint32_t fat_offset;    uint16_t cluster_max;    uint16_t cluster_next;    uint16_t count_left;
    uint8_t buffer[2];	uint16_t cluster_new;    if(!fs)        return 0;    device_read = fs->partition->device_read;    device_write = fs->partition->device_write;    fat_offset = fs->header.fat_offset;    cluster_max = (U16) (fs->header.fat_size >> 1);    cluster_next = 0;    count_left = count;    for(cluster_new = 0; cluster_new < cluster_max; ++cluster_new)    {        if(!device_read(fat_offset + 2 * cluster_new, buffer, sizeof(buffer)))            return 0;        /* check if this is a free cluster */        if(buffer[0] == (FAT16_CLUSTER_FREE & 0xff) &&           buffer[1] == ((FAT16_CLUSTER_FREE >> 8) & 0xff))        {            /* allocate cluster */            if(count_left == count)            {                buffer[0] = FAT16_CLUSTER_LAST_MAX & 0xff;                buffer[1] = (FAT16_CLUSTER_LAST_MAX >> 8) & 0xff;            }            else            {                buffer[0] = cluster_next & 0xff;                buffer[1] = (cluster_next >> 8) & 0xff;            }            if(!device_write(fat_offset + 2 * cluster_new, buffer, sizeof(buffer)))                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(cluster_num >= 2)        {            buffer[0] = cluster_next & 0xff;            buffer[1] = (cluster_next >> 8) & 0xff;            if(!device_write(fat_offset + 2 * cluster_num, buffer, sizeof(buffer)))                break;        }        return cluster_next;    } while(0);    /* No space left on device or writing error.     * Free up all clusters already allocated.     */    fat16_free_clusters(fs, cluster_next);    return 0;#else    return 0;#endif}/** * \ingroup fat16_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 fat16_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 fat16_terminate_clusters */uint8_t fat16_free_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num){#if FAT16_WRITE_SUPPORT    uint8_t buffer[2];
	uint32_t fat_offset;
    uint16_t cluster_num_next;
	if(!fs || cluster_num < 2)        return 0;    fat_offset = fs->header.fat_offset;        while(cluster_num)    {        if(!fs->partition->device_read(fat_offset + 2 * cluster_num, buffer, 2))            return 0;        /* get next cluster of current cluster before freeing current cluster */        cluster_num_next = ((uint16_t) buffer[0]) |                                    ((uint16_t) buffer[1] << 8);        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 */        buffer[0] = FAT16_CLUSTER_FREE & 0xff;        buffer[1] = (FAT16_CLUSTER_FREE >> 8) & 0xff;        fs->partition->device_write(fat_offset + 2 * cluster_num, buffer, 2);        /* 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;#else    return 0;#endif}/** * \ingroup fat16_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 fat16_free_clusters */uint8_t fat16_terminate_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num){#if FAT16_WRITE_SUPPORT

	uint16_t cluster_num_next;
	uint8_t buffer[2];

    if(!fs || cluster_num < 2)        return 0;    /* fetch next cluster before overwriting the cluster entry */    cluster_num_next = fat16_get_next_cluster(fs, cluster_num);    /* mark cluster as the last one */        buffer[0] = FAT16_CLUSTER_LAST_MAX & 0xff;    buffer[1] = (FAT16_CLUSTER_LAST_MAX >> 8) & 0xff;    if(!fs->partition->device_write(fs->header.fat_offset + 2 * cluster_num, buffer, 2))        return 0;    /* free remaining clusters */    if(cluster_num_next)        return fat16_free_clusters(fs, cluster_num_next);    else        return 1;#else    return 0;#endif}/** * \ingroup fat16_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 fat16_clear_cluster(const struct fat16_fs_struct* fs, uint16_t cluster_num){#if FAT16_WRITE_SUPPORT

    uint32_t cluster_offset;    uint8_t zero[64];	//old is 16
    if(cluster_num < 2)        return 0;    cluster_offset = fs->header.cluster_zero_offset +                              (uint32_t) (cluster_num - 2) * fs->header.cluster_size;    return fs->partition->device_write_interval(cluster_offset,                                                zero,                                                fs->header.cluster_size,                                                fat16_clear_cluster_callback,                                                0                                               );#else    return 0;#endif}/**

⌨️ 快捷键说明

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