📄 fs_fat32util.c
字号:
****************************************************************************/int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo){ ubyte *direntry; uint32 time; int ret; /* Set up the directory entry */ ret = fat_allocatedirentry(fs, dirinfo); if (ret != OK) { /* Failed to set up directory entry */ return ret; } /* Initialize the 32-byte directory entry */ direntry = dirinfo->fd_entry; memset(direntry, 0, 32); /* Directory name info */ memcpy(&direntry[DIR_NAME], dirinfo->fd_name, 8+3);#ifdef CONFIG_FLAT_LCNAMES DIR_PUTNTRES(dirinfo->fd_entry, dirinfo->fd_ntflags);#else DIR_PUTNTRES(dirinfo->fd_entry, 0);#endif /* ARCHIVE attribute, write time, creation time */ DIR_PUTATTRIBUTES(dirinfo->fd_entry, FATATTR_ARCHIVE); time = fat_systime2fattime(); DIR_PUTWRTTIME(dirinfo->fd_entry, time & 0xffff); DIR_PUTCRTIME(dirinfo->fd_entry, time & 0xffff); DIR_PUTWRTDATE(dirinfo->fd_entry, time >> 16); DIR_PUTCRDATE(dirinfo->fd_entry, time >> 16); fs->fs_dirty = TRUE; return OK;}/**************************************************************************** * Name: fat_remove * * Desciption: Remove a directory or file from the file system. This * implements both rmdir() and unlink(). * ****************************************************************************/int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory){ struct fat_dirinfo_s dirinfo; uint32 dircluster; size_t dirsector; int ret; /* Find the directory entry referring to the entry to be deleted */ ret = fat_finddirentry(fs, &dirinfo, relpath); if (ret != OK) { /* No such path */ return -ENOENT; } /* Check if this is a FAT12/16 root directory */ if (dirinfo.fd_entry == NULL) { /* The root directory cannot be removed */ return -EPERM; } /* The object has to have write access to be deleted */ if ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_READONLY) != 0) { /* It is a read-only entry */ return -EACCES; } /* Get the directory sector and cluster containing the * entry to be deleted */ dirsector = fs->fs_currentsector; dircluster = ((uint32)DIR_GETFSTCLUSTHI(dirinfo.fd_entry) << 16) | DIR_GETFSTCLUSTLO(dirinfo.fd_entry); /* Is this entry a directory? */ if (DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY) { /* It is a sub-directory. Check if we are be asked to remove * a directory or a file. */ if (!directory) { /* We are asked to delete a file */ return -EISDIR; } /* We are asked to delete a directory. Check if this * sub-directory is empty */ dirinfo.dir.fd_currcluster = dircluster; dirinfo.dir.fd_currsector = fat_cluster2sector(fs, dircluster); dirinfo.dir.fd_index = 2; /* Loop until either (1) an entry is found in the directory * (error), (2) the directory is found to be empty, or (3) some * error occurs. */ for (;;) { unsigned int subdirindex; ubyte *subdirentry; /* Make sure that the sector containing the of the * subdirectory sector is in the cache */ ret = fat_fscacheread(fs, dirinfo.dir.fd_currsector); if (ret < 0) { return ret; } /* Get a reference to the next entry in the directory */ subdirindex = (dirinfo.dir.fd_index & DIRSEC_NDXMASK(fs)) * 32; subdirentry = &fs->fs_buffer[subdirindex]; /* Is this the last entry in the direcory? */ if (subdirentry[DIR_NAME] == DIR0_ALLEMPTY) { /* Yes then the directory is empty. Break out of the * loop and delete the directory. */ break; } /* Check if the next entry refers to a file or directory */ if (subdirentry[DIR_NAME] != DIR0_EMPTY && !(DIR_GETATTRIBUTES(subdirentry) & FATATTR_VOLUMEID)) { /* The directory is not empty */ return -ENOTEMPTY; } /* Get the next directgory entry */ ret = fat_nextdirentry(fs, &dirinfo.dir); if (ret < 0) { return ret; } } } else { /* It is a file. Check if we are be asked to remove a directory * or a file. */ if (directory) { /* We are asked to remove a directory */ return -ENOTDIR; } } /* Make sure that the directory containing the entry to be deleted is * in the cache. */ ret = fat_fscacheread(fs, dirsector); if (ret < 0) { return ret; } /* Mark the directory entry 'deleted' */ dirinfo.fd_entry[DIR_NAME] = DIR0_EMPTY; fs->fs_dirty = TRUE; /* And remove the cluster chain making up the subdirectory */ ret = fat_removechain(fs, dircluster); if (ret < 0) { return ret; } /* Update the FSINFO sector (FAT32) */ ret = fat_updatefsinfo(fs); if (ret < 0) { return ret; } return OK;}/**************************************************************************** * Name: fat_fscacheflush * * Desciption: Flush any dirty sector if fs_buffer as necessary * ****************************************************************************/int fat_fscacheflush(struct fat_mountpt_s *fs){ int ret; /* Check if the fs_buffer is dirty. In this case, we will write back the * contents of fs_buffer. */ if (fs->fs_dirty) { /* Write the dirty sector */ ret = fat_hwwrite(fs, fs->fs_buffer, fs->fs_currentsector, 1); if (ret < 0) { return ret; } /* Does the sector lie in the FAT region? */ if (fs->fs_currentsector < fs->fs_fatbase + fs->fs_nfatsects) { /* Yes, then make the change in the FAT copy as well */ int i; for (i = fs->fs_fatnumfats; i >= 2; i--) { fs->fs_currentsector += fs->fs_nfatsects; ret = fat_hwwrite(fs, fs->fs_buffer, fs->fs_currentsector, 1); if (ret < 0) { return ret; } } } /* No longer dirty */ fs->fs_dirty = FALSE; } return OK;}/**************************************************************************** * Name: fat_fscacheread * * Desciption: Read the specified sector into the sector cache, flushing any * existing dirty sectors as necessary. * ****************************************************************************/int fat_fscacheread(struct fat_mountpt_s *fs, size_t sector){ int ret; /* fs->fs_currentsector holds the current sector that is buffered in * fs->fs_buffer. If the requested sector is the same as this sector, then * we do nothing. Otherwise, we will have to read the new sector. */ if (fs->fs_currentsector != sector) { /* We will need to read the new sector. First, flush the cached * sector if it is dirty. */ ret = fat_fscacheflush(fs); if (ret < 0) { return ret; } /* Then read the specified sector into the cache */ ret = fat_hwread(fs, fs->fs_buffer, sector, 1); if (ret < 0) { return ret; } /* Update the cached sector number */ fs->fs_currentsector = sector; } return OK;}/**************************************************************************** * Name: fat_ffcacheflush * * Desciption: Flush any dirty sectors as necessary * ****************************************************************************/int fat_ffcacheflush(struct fat_mountpt_s *fs, struct fat_file_s *ff){ int ret; /* Check if the ff_buffer is dirty. In this case, we will write back the * contents of ff_buffer. */ if (ff->ff_bflags && (FFBUFF_DIRTY|FFBUFF_VALID) == (FFBUFF_DIRTY|FFBUFF_VALID)) { /* Write the dirty sector */ ret = fat_hwwrite(fs, ff->ff_buffer, ff->ff_currentsector, 1); if (ret < 0) { return ret; } /* No longer dirty */ ff->ff_bflags &= ~FFBUFF_DIRTY; } return OK;}/**************************************************************************** * Name: fat_ffcacheread * * Desciption: Read the specified sector into the sector cache, flushing any * existing dirty sectors as necessary. * ****************************************************************************/int fat_ffcacheread(struct fat_mountpt_s *fs, struct fat_file_s *ff, size_t sector){ int ret; /* ff->ff_currentsector holds the current sector that is buffered in * ff->ff_buffer. If the requested sector is the same as this sector, then * we do nothing. Otherwise, we will have to read the new sector. */ if (ff->ff_currentsector != sector || (ff->ff_bflags & FFBUFF_VALID) == 0) { /* We will need to read the new sector. First, flush the cached * sector if it is dirty. */ ret = fat_ffcacheflush(fs, ff); if (ret < 0) { return ret; } /* Then read the specified sector into the cache */ ret = fat_hwread(fs, ff->ff_buffer, sector, 1); if (ret < 0) { return ret; } /* Update the cached sector number */ ff->ff_currentsector = sector; ff->ff_bflags |= FFBUFF_VALID; } return OK;}/**************************************************************************** * Name: fat_ffcacheread * * Desciption: Invalidate the current file buffer contents * ****************************************************************************/int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff){ int ret; /* Is there anything valid in the buffer now? */ if ((ff->ff_bflags & FFBUFF_VALID) != 0) { /* We will invalidate the buffered sector */ ret = fat_ffcacheflush(fs, ff); if (ret < 0) { return ret; } /* Then discard the current cache contents */ ff->ff_bflags &= ~FFBUFF_VALID; } return OK;}/**************************************************************************** * Name: fat_updatefsinfo * * Desciption: Flush evertyhing buffered for the mountpoint and update * the FSINFO sector, if appropriate * ****************************************************************************/int fat_updatefsinfo(struct fat_mountpt_s *fs){ int ret; /* Flush the fs_buffer if it is dirty */ ret = fat_fscacheflush(fs); if (ret == OK) { /* The FSINFO sector only has to be update for the case of a FAT32 file * system. Check if the file system type.. If this is a FAT32 file * system then the fs_fsidirty flag will indicate if the FSINFO sector * needs to be re-written. */ if (fs->fs_type == FSTYPE_FAT32 && fs->fs_fsidirty) { /* Create an image of the FSINFO sector in the fs_buffer */ memset(fs->fs_buffer, 0, fs->fs_hwsectorsize); FSI_PUTLEADSIG(fs->fs_buffer, 0x41615252); FSI_PUTSTRUCTSIG(fs->fs_buffer, 0x61417272); FSI_PUTFREECOUNT(fs->fs_buffer, fs->fs_fsifreecount); FSI_PUTNXTFREE(fs->fs_buffer, fs->fs_fsinextfree); FSI_PUTTRAILSIG(fs->fs_buffer, BOOT_SIGNATURE32); /* Then flush this to disk */ fs->fs_currentsector = fs->fs_fsinfo; fs->fs_dirty = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -