📄 fs_fat32util.c
字号:
startsector >>= 4; } else { /* Even.. take the LS 12-bits */ startsector &= 0x0fff; } return startsector; } case FSTYPE_FAT16 : { unsigned int fatoffset = 2 * clusterno; size_t fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); unsigned int fatindex = fatoffset & SEC_NDXMASK(fs); if (fat_fscacheread(fs, fatsector) < 0) { /* Read error */ break; } return FAT_GETFAT16(fs->fs_buffer, fatindex); } case FSTYPE_FAT32 : { unsigned int fatoffset = 4 * clusterno; size_t fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); unsigned int fatindex = fatoffset & SEC_NDXMASK(fs); if (fat_fscacheread(fs, fatsector) < 0) { /* Read error */ break; } return FAT_GETFAT16(fs->fs_buffer, fatindex) & 0x0fffffff; } default: break; } } /* There is no cluster information, or an error occured */ return (ssize_t)-EINVAL;}/**************************************************************************** * Name: fat_putcluster * * Desciption: Write a new cluster start sector into the FAT * ****************************************************************************/int fat_putcluster(struct fat_mountpt_s *fs, uint32 clusterno, size_t startsector){ /* Verify that the cluster number is within range. Zero erases the cluster. */ if (clusterno == 0 || (clusterno >= 2 && clusterno < fs->fs_nclusters)) { /* Okay.. Write the next cluster into the FAT. The way we will do * this depends on the type of FAT filesystm we are dealing with. */ switch (fs->fs_type) { case FSTYPE_FAT12 : { size_t fatsector; unsigned int fatoffset; unsigned int fatindex; ubyte value; /* FAT12 is more complex because it has 12-bits (1.5 bytes) * per FAT entry. Get the offset to the first byte: */ fatoffset = (clusterno * 3) / 2; fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); /* Make sure that the sector at this offset is in the cache */ if (fat_fscacheread(fs, fatsector)< 0) { /* Read error */ break; } /* Output the LS byte first handling the 12-bit alignment within * the 16-bits */ fatindex = fatoffset & SEC_NDXMASK(fs); if ((clusterno & 1) != 0) { value = (fs->fs_buffer[fatindex] & 0x0f) | startsector << 4; } else { value = (ubyte)startsector; } fs->fs_buffer[fatindex] = value; /* With FAT12, the second byte of the cluster number may lie in * a different sector than the first byte. */ fatindex++; if (fatindex >= fs->fs_hwsectorsize) { /* Read the next sector */ fatsector++; fatindex = 0; /* Set the dirty flag to make sure the sector that we * just modified is written out. */ fs->fs_dirty = TRUE; if (fat_fscacheread(fs, fatsector) < 0) { /* Read error */ break; } } /* Output the MS byte first handling the 12-bit alignment within * the 16-bits */ if ((clusterno & 1) != 0) { value = (ubyte)(startsector >> 4); } else { value = (fs->fs_buffer[fatindex] & 0xf0) | (startsector & 0x0f); } fs->fs_buffer[fatindex] = value; } break; case FSTYPE_FAT16 : { unsigned int fatoffset = 2 * clusterno; size_t fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); unsigned int fatindex = fatoffset & SEC_NDXMASK(fs); if (fat_fscacheread(fs, fatsector) < 0) { /* Read error */ break; } FAT_PUTFAT16(fs->fs_buffer, fatindex, startsector & 0xffff); } break; case FSTYPE_FAT32 : { unsigned int fatoffset = 4 * clusterno; size_t fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); unsigned int fatindex = fatoffset & SEC_NDXMASK(fs); if (fat_fscacheread(fs, fatsector) < 0) { /* Read error */ break; } FAT_PUTFAT32(fs->fs_buffer, fatindex, startsector & 0x0fffffff); } break; default: return -EINVAL; } /* Mark the modified sector as "dirty" and return success */ fs->fs_dirty = 1; return OK; } return -EINVAL;}/**************************************************************************** * Name: fat_removechain * * Desciption: Remove an entire chain of clusters, starting with 'cluster' * ****************************************************************************/int fat_removechain(struct fat_mountpt_s *fs, uint32 cluster){ sint32 nextcluster; int ret; /* Loop while there are clusters in the chain */ while (cluster >= 2 && cluster < fs->fs_nclusters) { /* Get the next cluster after the current one */ nextcluster = fat_getcluster(fs, cluster); if (nextcluster < 0) { /* Error! */ return nextcluster; } /* Then nullify current cluster -- removing it from the chain */ ret = fat_putcluster(fs, cluster, 0); if (ret < 0) { return ret; } /* Update FSINFINFO data */ if (fs->fs_fsifreecount != 0xffffffff) { fs->fs_fsifreecount++; fs->fs_fsidirty = 1; } /* Then set up to remove the next cluster */ cluster = nextcluster; } return OK;}/**************************************************************************** * Name: fat_extendchain * * Desciption: Add a new cluster to the chain following cluster (if cluster * is non-NULL). if cluster is zero, then a new chain is created. * * Return: <0:error, 0: no free cluster, >=2: new cluster number * ****************************************************************************/sint32 fat_extendchain(struct fat_mountpt_s *fs, uint32 cluster){ ssize_t startsector; uint32 newcluster; uint32 startcluster; int ret; /* The special value 0 is used when the new chain should start */ if (cluster == 0) { /* The FSINFO NextFree entry should be a good starting point * in the search for a new cluster */ startcluster = fs->fs_fsinextfree; if (startcluster == 0 || startcluster >= fs->fs_nclusters) { /* But it is bad.. we have to start at the beginning */ startcluster = 1; } } else { /* We are extending an existing chain. Verify that this * is a valid cluster by examining its start sector. */ startsector = fat_getcluster(fs, cluster); if (startsector < 0) { /* An error occurred, return the error value */ return startsector; } else if (startsector < 2) { /* Oops.. this cluster does not exist. */ return 0; } else if (startsector < fs->fs_nclusters) { /* It is already followed by next cluster */ return startsector; } /* Okay.. it checks out */ startcluster = cluster; } /* Loop until (1) we discover that there are not free clusters * (return 0), an errors occurs (return -errno), or (3) we find * the next cluster (return the new cluster number). */ newcluster = startcluster; for (;;) { /* Examine the next cluster in the FAT */ newcluster++; if (newcluster >= fs->fs_nclusters) { /* If we hit the end of the available clusters, then * wrap back to the beginning because we might have * started at a non-optimal place. But don't continue * past the start cluster. */ newcluster = 2; if (newcluster > startcluster) { /* We are back past the starting cluster, then there * is no free cluster. */ return 0; } } /* We have a candidate cluster. Check if the cluster number is * mapped to a group of sectors. */ startsector = fat_getcluster(fs, newcluster); if (startsector == 0) { /* Found have found a free cluster break out*/ break; } else if (startsector < 0) { /* Some error occurred, return the error number */ return startsector; } /* We wrap all the back to the starting cluster? If so, then * there are no free clusters. */ if (newcluster == startcluster) { return 0; } } /* We get here only if we break out with an available cluster * number in 'newcluster' Now mark that cluster as in-use. */ ret = fat_putcluster(fs, newcluster, 0x0fffffff); if (ret < 0) { /* An error occurred */ return ret; } /* And link if to the start cluster (if any)*/ if (cluster) { /* There is a start cluster -- link it */ ret = fat_putcluster(fs, cluster, newcluster); if (ret < 0) { return ret; } } /* And update the FINSINFO for the next time we have to search */ fs->fs_fsinextfree = newcluster; if (fs->fs_fsifreecount != 0xffffffff) { fs->fs_fsifreecount--; fs->fs_fsidirty = 1; } /* Return then number of the new cluster that was added to the chain */ return newcluster;}/**************************************************************************** * Name: fat_nextdirentry * * Desciption: Read the next directory entry from the sector in cache, * reading the next sector(s) in the cluster as necessary. * ****************************************************************************/int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir){ unsigned int cluster; unsigned int ndx; /* Increment the index to the next 32-byte directory entry */ ndx = dir->fd_index + 1; /* Check if all of the directory entries in this sectory have * been examined. */ if ((ndx & (DIRSEC_NDIRS(fs)-1)) == 0) { /* Yes, then we will have to read the next sector */ dir->fd_currsector++; /* For FAT12/16, the root directory is a group of sectors relative * to the first sector of the fat volume. */ if (!dir->fd_currcluster) { /* For FAT12/16, the boot record tells us number of 32-bit directories * that are contained in the root directory. This should correspond to * an even number of sectors. */ if (ndx >= fs->fs_rootentcnt) { /* When we index past this count, we have examined all of the entries in * the root directory. */ return ERROR; } } else { /* Not a FAT12/16 root directory, check if we have examined the entire * cluster comprising the directory. * * The current sector within the cluster is the entry number divided * byte the number of entries per sector */ int sector = ndx / DIRSEC_NDIRS(fs); /* We are finished with the cluster when the last sector of the cluster * has been examined. */ if ((sector & (fs->fs_fatsecperclus-1)) == 0) { /* Get next cluster */ cluster = fat_getcluster(fs, dir->fd_currcluster); /* Check if a valid cluster was obtained. */ if (cluster < 2 || cluster >= fs->fs_nclusters) { /* No, we have probably reached the end of the cluster list */ return ERROR; } /* Initialize for new cluster */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -