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

📄 fat16.c

📁 SD卡调试所用的资料
💻 C
📖 第 1 页 / 共 5 页
字号:
        if(!fs->partition->device_read(offset, &first_char, sizeof(first_char)))
            return 0;

        /* check if we found a free directory entry */
        if(first_char == FAT16_DIRENTRY_DELETED || !first_char)
        {
            /* check if we have the needed number of available entries */
            ++free_dir_entries_found;
            if(free_dir_entries_found >= free_dir_entries_needed)
                break;

            offset += 32;
        }
        else
        {
            offset += 32;
            Dir_Entry_Offset = offset;
            free_dir_entries_found = 0;
        }
    }

    return Dir_Entry_Offset;

#else
    return 0;
#endif
}



/**********************************************************************
*  函数 Fat16_Write_Dir_Entry --- 添加一条目录项
* 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.
*
*   输入参数 fs:The filesystem on which to operate  
*            dir_entry:The directory entry to write.
*   返回值  0 --- 失败 
*           1 --- 成功
**********************************************************************/
u8 
Fat16_Write_Dir_Entry(const struct Fat16_FS_Struct* fs, struct Fat16_Dir_Entry_Struct* dir_entry)
{
#if FAT16_WRITE_SUPPORT
    if(!fs || !dir_entry)
        return 0;

#if FAT16_DATETIME_SUPPORT
    {
        u16 year;
        u8 month;
        u8 day;
        u8 hour;
        u8 min;
        u8 sec;

        fat16_get_datetime(&year, &month, &day, &hour, &min, &sec);
        fat16_set_file_modification_date(dir_entry, year, month, day);
        fat16_set_file_modification_time(dir_entry, hour, min, sec);
    }
#endif

    device_write_t device_write = fs->partition->device_write;
    u32 offset = dir_entry->Entry_Offset;
    const char* name = dir_entry->Long_Name;
    u8 name_len = strlen(name);
    u8 lfn_entry_count = (name_len + 12) / 13;
    u8 buffer[32];

    /* write 8.3 entry */

    /* generate 8.3 file name */
    memset(&buffer[0], ' ', 11);
    char* name_ext = strrchr(name, '.');
    if(name_ext && *++name_ext)
    {
        u8 name_ext_len = strlen(name_ext);
        name_len -= name_ext_len + 1;

        if(name_ext_len > 3)
            name_ext_len = 3;

        memcpy(&buffer[8], name_ext, name_ext_len);
    }

    if(name_len <= 8)
    {
        memcpy(buffer, name, name_len);

        /* For now, we create lfn entries for all files,
         * except the "." and ".." directory references.
         * This is to avoid difficulties with capitalization,
         * as 8.3 filenames allow uppercase letters only.
         *
         * Theoretically it would be possible to leave
         * the 8.3 entry alone if the basename and the
         * extension have no mixed capitalization.
         */
        if(name[0] == '.' &&
           ((name[1] == '.' && name[2] == '\0') ||
            name[1] == '\0')
          )
            lfn_entry_count = 0;
    }
    else
    {
        memcpy(buffer, name, 8);

        /* Minimize 8.3 name clashes by appending
         * the lower byte of the cluster number.
         */
        u8 num = dir_entry->Cluster & 0xff;

        buffer[6] = (num < 0xa0) ? ('0' + (num >> 4)) : ('a' + (num >> 4));
        num &= 0x0f;
        buffer[7] = (num < 0x0a) ? ('0' + num) : ('a' + num);
    }
    if(buffer[0] == FAT16_DIRENTRY_DELETED)
        buffer[0] = 0x05;

    /* fill directory entry buffer */
    memset(&buffer[11], 0, sizeof(buffer) - 11);
    buffer[0x0b] = dir_entry->Attributes;
#if FAT16_DATETIME_SUPPORT
    buffer[0x16] = (dir_entry->modification_time >> 0) & 0xff;
    buffer[0x17] = (dir_entry->modification_time >> 8) & 0xff;
    buffer[0x18] = (dir_entry->modification_date >> 0) & 0xff;
    buffer[0x19] = (dir_entry->modification_date >> 8) & 0xff;
#endif
    buffer[0x1a] = (dir_entry->Cluster >> 0) & 0xff;
    buffer[0x1b] = (dir_entry->Cluster >> 8) & 0xff;
    buffer[0x1c] = (dir_entry->File_Size >> 0) & 0xff;
    buffer[0x1d] = (dir_entry->File_Size >> 8) & 0xff;
    buffer[0x1e] = (dir_entry->File_Size >> 16) & 0xff;
    buffer[0x1f] = (dir_entry->File_Size >> 24) & 0xff;

    /* write to disk */
    if(!device_write(offset + (u32) lfn_entry_count * 32, buffer, sizeof(buffer)))
        return 0;

    /* calculate checksum of 8.3 name */
    u8 checksum = buffer[0];
    for(u8 i = 1; i < 11; ++i)
        checksum = ((checksum >> 1) | (checksum << 7)) + buffer[i];

    /* write lfn entries */
    for(u8 lfn_entry = lfn_entry_count; lfn_entry > 0; --lfn_entry)
    {
        memset(buffer, 0xff, sizeof(buffer));

        /* set file name */
        const char* Long_Name_curr = name + (lfn_entry - 1) * 13;
        u8 i = 1;
        while(i < 0x1f)
        {
            buffer[i++] = *Long_Name_curr;
            buffer[i++] = 0;

            switch(i)
            {
                case 0x0b:
                    i = 0x0e;
                    break;
                case 0x1a:
                    i = 0x1c;
                    break;
            }

            if(!*Long_Name_curr++)
                break;
        }

        /* set index of lfn entry */
        buffer[0x00] = lfn_entry;
        if(lfn_entry == lfn_entry_count)
            buffer[0x00] |= FAT16_DIRENTRY_LFNLAST;

        /* mark as lfn entry */
        buffer[0x0b] = 0x0f;

        /* 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
}



/**********************************************************************
*  函数 Fat16_Create_File --- 创建文件
* note:
*     创建文件并返回文件路径信息,如果文件已经存在,则创建失败,并返回
* 已存在文件的信息存放于 dir_entry
*
*   输入参数 parent:The handle of the directory in which to create the file. 
*            file:The name of the file to create.
*   输出参数 dir_entry:The directory entry to fill for the new file.
*   返回值  0 --- 失败 
*           1 --- 成功
**********************************************************************/
u8 
Fat16_Create_File(struct Fat16_Dir_Struct*        parent,
                  const char*                     file,
                  struct Fat16_Dir_Entry_Struct*  dir_entry)
{
#if FAT16_WRITE_SUPPORT
    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;
        }
    }

    struct Fat16_FS_Struct* 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 */
    if(!(dir_entry->Entry_Offset = Fat16_Find_Offset_For_Dir_Entry(fs, parent, dir_entry)))
        return 0;

    /* write directory entry to disk */
    if(!Fat16_Write_Dir_Entry(fs, dir_entry))
        return 0;

    return 1;

#else
    return 0;
#endif
}



/**********************************************************************
*  函数 Fat16_Delete_File --- 删除文件或者目录
* note:
*     如果删除目录前,没有删除其子目录和子文件,其占用的空间将被浪费,
* 子目录和子文件将不会被释放出来
*
*   输入参数 fs:The filesystem on which to operate. 
*            dir_entry:The directory entry of the file to delete.
*   返回值  0 --- 失败 
*           1 --- 成功
**********************************************************************/
u8 
Fat16_Delete_File(struct Fat16_FS_Struct* fs, struct Fat16_Dir_Entry_Struct* dir_entry)
{
#if FAT16_WRITE_SUPPORT
    if(!fs || !dir_entry)
        return 0;

    /* get offset of the file's directory entry */
    u32 Dir_Entry_Offset = dir_entry->Entry_Offset;
    if(!Dir_Entry_Offset)
        return 0;

    u8 buffer[12];
    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
}



/**********************************************************************
*  函数 Fat16_Create_Dir --- 创建一个目录
* note:
*     创建目录并返回目录路径信息,如果目录已经存在,则创建失败,并返回
* 已存在目录的信息存放于 dir_entry
*
*   输入参数 parent:The handle of the parent directory of the new directory. 
*            dir:The name of the directory to create.
*            dir_entry:The directory entry to fill for the new directory.
*   返回值  0 --- 失败 
*           1 --- 成功
**********************************************************************/
u8 
Fat16_Create_Dir(struct Fat16_Dir_Struct*         parent,
                 const char*                      dir, 
                 struct Fat16_Dir_Entry_Struct*   dir_entry)
{
#if FAT16_WRITE_SUPPORT
    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;
        }
    }

    struct Fat16_FS_Struct* fs = parent->fs;

    /* allocate cluster which will hold directory entries */
    u16 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 +
                              (u32) (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 */
    if(!(dir_entry->Entry_Offset = Fat16_Find_Offset_For_Dir_Entry(fs, parent, dir_entry)))
    {
        Fat16_Free_Clusters(fs, dir_cluster);
        return 0;
    }

    /* write directory to disk */
    if(!Fat16_Write_Dir_Entry(fs, dir_entry))
    {
        Fat16_Free_Clusters(

⌨️ 快捷键说明

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