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

📄 fat16.c

📁 包装了一个开源的FAT16文件系统
💻 C
📖 第 1 页 / 共 5 页
字号:
        /* set 8.3 checksum */        buffer[0x0d] = checksum;        /* clear reserved bytes */        buffer[0x0c] = 0;        buffer[0x1a] = 0;        buffer[0x1b] = 0;        /* write entry */        device_write(offset, buffer, sizeof(buffer));            offset += sizeof(buffer);    }        return 1;#else    return 0;#endif}/** * \ingroup fat16_file * 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. * * \note 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. * * \param[in] parent The handle of the directory in which to create the file. * \param[in] file The name of the file to create. * \param[out] dir_entry The directory entry to fill for the new file. * \returns 0 on failure, 1 on success. * \see fat16_delete_file */uint8_t fat16_create_file(struct fat16_dir_struct* parent, const char* file, struct fat16_dir_entry_struct* dir_entry){#if FAT16_WRITE_SUPPORT    
	struct fat16_fs_struct* fs;
	
	if(!parent || !file || !file[0] || !dir_entry)        return 0;    /* check if the file already exists */    while(1)    {        if(!fat16_read_dir(parent, dir_entry))            break;        if(strcmp(file, dir_entry->long_name) == 0)        {            fat16_reset_dir(parent);            return 0;        }    }    fs = parent->fs;    /* prepare directory entry with values already known */    memset(dir_entry, 0, sizeof(*dir_entry));    strncpy(dir_entry->long_name, file, sizeof(dir_entry->long_name) - 1);    /* find place where to store directory entry */
	dir_entry->entry_offset = fat16_find_offset_for_dir_entry(fs, parent, dir_entry);    if(!dir_entry->entry_offset)        return 0;        /* write directory entry to disk */    if(!fat16_write_dir_entry(fs, dir_entry))        return 0;        return 1;    #else    return 0;#endif}/** * \ingroup fat16_file * 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. *  * \param[in] fs The filesystem on which to operate. * \param[in] dir_entry The directory entry of the file to delete. * \returns 0 on failure, 1 on success. * \see fat16_create_file */uint8_t fat16_delete_file(struct fat16_fs_struct* fs, struct fat16_dir_entry_struct* dir_entry){#if FAT16_WRITE_SUPPORT

	uint32_t dir_entry_offset;
	uint8_t buffer[12];
    if(!fs || !dir_entry)        return 0;    /* get offset of the file's directory entry */    dir_entry_offset = dir_entry->entry_offset;    if(!dir_entry_offset)        return 0;        while(1)    {        /* read directory entry */        if(!fs->partition->device_read(dir_entry_offset, buffer, sizeof(buffer)))            return 0;                /* mark the directory entry as deleted */        buffer[0] = FAT16_DIRENTRY_DELETED;                /* write back entry */        if(!fs->partition->device_write(dir_entry_offset, buffer, sizeof(buffer)))            return 0;        /* check if we deleted the whole entry */        if(buffer[11] != 0x0f)            break;        dir_entry_offset += 32;    }    /* We deleted the directory entry. The next thing to do is     * marking all occupied clusters as free.     */    return (dir_entry->cluster == 0 || fat16_free_clusters(fs, dir_entry->cluster));#else    return 0;#endif}/** * \ingroup fat16_dir * Creates a directory. * * Creates a directory and obtains its directory entry. * If the directory to create already exists, its * directory entry will be returned within the dir_entry * parameter. * * \note The notes which apply to fat16_create_file also * apply to this function. * * \param[in] parent The handle of the parent directory of the new directory. * \param[in] dir The name of the directory to create. * \param[out] dir_entry The directory entry to fill for the new directory. * \returns 0 on failure, 1 on success. * \see fat16_delete_dir */uint8_t fat16_create_dir(struct fat16_dir_struct* parent, const char* dir, struct fat16_dir_entry_struct* dir_entry){#if FAT16_WRITE_SUPPORT

	struct fat16_fs_struct* fs;
	uint16_t dir_cluster;
    if(!parent || !dir || !dir[0] || !dir_entry)        return 0;    /* check if the file or directory already exists */    while(1)    {        if(!fat16_read_dir(parent, dir_entry))            break;        if(strcmp(dir, dir_entry->long_name) == 0)        {            fat16_reset_dir(parent);            return 0;        }    }    fs = parent->fs;    /* allocate cluster which will hold directory entries */    dir_cluster = fat16_append_clusters(fs, 0, 1);    if(!dir_cluster)        return 0;    /* clear cluster to prevent bogus directory entries */    fat16_clear_cluster(fs, dir_cluster);        memset(dir_entry, 0, sizeof(*dir_entry));    dir_entry->attributes = FAT16_ATTRIB_DIR;    /* create "." directory self reference */    dir_entry->entry_offset = fs->header.cluster_zero_offset +                              (uint32_t) (dir_cluster - 2) * fs->header.cluster_size;    dir_entry->long_name[0] = '.';    dir_entry->cluster = dir_cluster;    if(!fat16_write_dir_entry(fs, dir_entry))    {        fat16_free_clusters(fs, dir_cluster);        return 0;    }    /* create ".." parent directory reference */    dir_entry->entry_offset += 32;    dir_entry->long_name[1] = '.';    dir_entry->cluster = parent->dir_entry.cluster;    if(!fat16_write_dir_entry(fs, dir_entry))    {        fat16_free_clusters(fs, dir_cluster);        return 0;    }    /* fill directory entry */    strncpy(dir_entry->long_name, dir, sizeof(dir_entry->long_name) - 1);    dir_entry->cluster = dir_cluster;    /* find place where to store directory entry */
	dir_entry->entry_offset = fat16_find_offset_for_dir_entry(fs, parent, dir_entry);    if(!dir_entry->entry_offset)    {        fat16_free_clusters(fs, dir_cluster);        return 0;    }    /* write directory to disk */    if(!fat16_write_dir_entry(fs, dir_entry))    {        fat16_free_clusters(fs, dir_cluster);        return 0;    }    return 1;    #else    return 0;#endif}/** * \ingroup fat16_dir * Deletes a directory. * * This is just a synonym for fat16_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. *  * \param[in] fs The filesystem on which to operate. * \param[in] dir_entry The directory entry of the directory to delete. * \returns 0 on failure, 1 on success. * \see fat16_create_dir */#ifdef DOXYGENuint8_t fat16_delete_dir(struct fat16_fs_struct* fs, struct fat16_dir_entry_struct* dir_entry);#endif/** * \ingroup fat16_file * Returns the modification date of a file. * * \param[in] dir_entry The directory entry of which to return the modification date. * \param[out] year The year the file was last modified. * \param[out] month The month the file was last modified. * \param[out] day The day the file was last modified. */void fat16_get_file_modification_date(const struct fat16_dir_entry_struct* dir_entry, uint16_t* year, uint8_t* month, uint8_t* day){#if FAT16_DATETIME_SUPPORT    if(!dir_entry)        return;    *year = 1980 + ((dir_entry->modification_date >> 9) & 0x7f);    *month = (dir_entry->modification_date >> 5) & 0x0f;    *day = (dir_entry->modification_date >> 0) & 0x1f;#endif}/** * \ingroup fat16_file * Returns the modification time of a file. * * \param[in] dir_entry The directory entry of which to return the modification time. * \param[out] hour The hour the file was last modified. * \param[out] min The min the file was last modified. * \param[out] sec The sec the file was last modified. */void fat16_get_file_modification_time(const struct fat16_dir_entry_struct* dir_entry, uint8_t* hour, uint8_t* min, uint8_t* sec){#if FAT16_DATETIME_SUPPORT    if(!dir_entry)        return;    *hour = (dir_entry->modification_time >> 11) & 0x1f;    *min = (dir_entry->modification_time >> 5) & 0x3f;    *sec = ((dir_entry->modification_time >> 0) & 0x1f) * 2;#endif}/** * \ingroup fat16_file * Sets the modification time of a date. * * \param[in] dir_entry The directory entry for which to set the modification date. * \param[in] year The year the file was last modified. * \param[in] month The month the file was last modified. * \param[in] day The day the file was last modified. */void fat16_set_file_modification_date(struct fat16_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day){#if FAT16_WRITE_SUPPORT#if FAT16_DATETIME_SUPPORT    if(!dir_entry)        return;    dir_entry->modification_date =        ((year - 1980) << 9) |        ((uint16_t) month << 5) |        ((uint16_t) day << 0);#endif#endif}/** * \ingroup fat16_file * Sets the modification time of a file. * * \param[in] dir_entry The directory entry for which to set the modification time. * \param[in] hour The year the file was last modified. * \param[in] min The month the file was last modified. * \param[in] sec The day the file was last modified. */void fat16_set_file_modification_time(struct fat16_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec){#if FAT16_WRITE_SUPPORT#if FAT16_DATETIME_SUPPORT    if(!dir_entry)        return;    dir_entry->modification_time =        ((uint16_t) hour << 11) |        ((uint16_t) min << 5) |        ((uint16_t) sec >> 1) ;#endif#endif}/** * \ingroup fat16_fs * Returns the amount of total storage capacity of the filesystem in bytes. * * \param[in] fs The filesystem on which to operate. * \returns 0 on failure, the filesystem size in bytes otherwise. */uint32_t fat16_get_fs_size(const struct fat16_fs_struct* fs){    if(!fs)        return 0;    return (fs->header.fat_size / 2 - 2) * fs->header.cluster_size;}/** * \ingroup fat16_fs * Returns the amount of free storage capacity on the filesystem in bytes. * * \note As the FAT16 filesystem is cluster based, this function does not *       return continuous values but multiples of the cluster size. * * \param[in] fs The filesystem on which to operate. * \returns 0 on failure, the free filesystem space in bytes otherwise. */uint32_t fat16_get_fs_free(const struct fat16_fs_struct* fs){
    uint8_t fat[32];    struct fat16_usage_count_callback_arg count_arg;
    uint32_t fat_offset;    uint32_t fat_size;


    if(!fs)        return 0;    count_arg.cluster_count = 0;    count_arg.buffer_size = sizeof(fat);    fat_offset = fs->header.fat_offset;    fat_size = fs->header.fat_size;    
	while(fat_size > 0)    {        uint16_t length = UINT16_MAX - 1;        if(fat_size < length)            length = (U16) fat_size;        if(!fs->partition->device_read_interval(fat_offset,                                                fat,                                                sizeof(fat),                                                length,                                                fat16_get_fs_free_callback,                                                &count_arg                                               )          )            return 0;        fat_offset += length;        fat_size -= length;    }    return (uint32_t) count_arg.cluster_count * fs->header.cluster_size;}/** * \ingroup fat16_fs * Callback function used for counting free clusters. */uint8_t fat16_get_fs_free_callback(uint8_t* buffer, uint32_t offset, void* p){    struct fat16_usage_count_callback_arg* count_arg = (struct fat16_usage_count_callback_arg*) p;    uint8_t buffer_size = count_arg->buffer_size;	uint8_t i;    for(i = 0; i < buffer_size; i += 2)    {        if((((uint16_t) buffer[1] << 8) | ((uint16_t) buffer[0] << 0)) == FAT16_CLUSTER_FREE)            ++(count_arg->cluster_count);        buffer += 2;    }    return 1;}

⌨️ 快捷键说明

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