void* loadFile(char *filename){ DirLayout *dir = searchFile(filename); UCHAR *start = kmalloc(dir->size); //コピー先確保 UCHAR *seek = start; int cl_num = dir->head_cluster; int limit = dir->size / CLUSTER_SIZE + (dir->size % CLUSTER_SIZE==0?0:1); int cnt=1; if(start == 0)return 0;//mallocできなかった while(cl_num != 0xfff){ if(cnt==INF)return 0;//FATがうまく読めてない //最後のあまりをコピー if(cnt==limit){ kmemcpy(seek,getClusterAdd(cl_num),dir->size%CLUSTER_SIZE); break; } kmemcpy(seek,getClusterAdd(cl_num),CLUSTER_SIZE); cl_num = getNextCluster(cl_num); seek += CLUSTER_SIZE; cnt++; } /* if(filename[0]=='l' && filename[1]=='i'){ asm volatile("cli"); asm volatile("mov %0,%%eax"::"r"((int)dir):"eax"); for(;;)asm volatile("hlt"); } */ return start; }
void FileBox::getClusterChain(){ unsigned long int *chain, link, length= 1; chain= (unsigned long int*)malloc(sizeof(unsigned long int) * length); chain[0]= 0x0FFFFFFF; SerialUSB.println(startCluster, DEC); while(3.14); link= getNextCluster(startCluster); while(link != 0x0FFFFFFF){ chain[length - 1]= link; length++; chain= (unsigned long int*)realloc(chain, sizeof(unsigned long int) * length); link= getNextCluster(link); } chainLength= length; clusterChain= chain; }
void FileBox::addLink(){ unsigned long int freeQ= 0; unsigned long int clusterQ= clusterChain[chainLength - 1] + 4; freeQ= getNextCluster(clusterQ); freeQ &= 0x0FFFFFFF; while(freeQ != 0){} }
/* * This function sets the size attribute of a specified directory entry. * currentDirCluster is the first cluster of the current directory. * targetEntry is the entry to be updated. * newBytes is the number of bytes to set as the total size. */ void setFileSize(FILE *fileImgPtr, unsigned int currentDirCluster, unsigned char *targetEntry, int newSize) { unsigned char entry[32]; unsigned int nextCluster; // Break the file's size into 4 characters. unsigned char sizeA = (newSize & 0xFF000000) >> 24; unsigned char sizeB = (newSize & 0x00FF0000) >> 16; unsigned char sizeC = (newSize & 0x0000FF00) >> 8; unsigned char sizeD = (newSize & 0x000000FF); nextCluster = currentDirCluster; // Loop until the end of cluster chain is reached or the entry is found. do { // Seek to the cluster's first sector. fseek(fileImgPtr, (getSector(nextCluster) * fsMetadata[BYTES_PER_SECTOR]), SEEK_SET); // Loop once for each directory entry that can fit in the sector. for(int i = 0; i < 16; ++i) { // Read in a directory entry. for(int j = 0; j < 32; ++j) { entry[j] = getc(fileImgPtr); } // If the entry is a long name entry, do not add it. if((entry[11] | 0xF0) == 0xFF) continue; // If the entry is empty, do not add it. if(entry[0] == 0xE5) continue; // If the entry is free, and is the last entry, end the entire function. if(entry[0] == 0x00) return; // Compare the directory entries. If they have the same first cluster // numbers, they are the same entry. if(targetEntry[20] == entry[20] && targetEntry[21] == entry[21] && targetEntry[26] == entry[26] && targetEntry[27] == entry[27]) { // This is the entry whose size we want to update. // Move the file pointer back 4 bytes and write the new size. fseek(fileImgPtr, -4, SEEK_CUR); putc(sizeD, fileImgPtr); putc(sizeC, fileImgPtr); putc(sizeB, fileImgPtr); putc(sizeA, fileImgPtr); return; } } // If next cluster not EOC, set next cluster to next cluster in chain. nextCluster = getNextCluster(fileImgPtr, nextCluster); } while(nextCluster < EOCMIN); }
//指定アドレスにファイルをロード void* loadFileToMem(void *add,char *filename){ DirLayout *dir = searchFile(filename); UCHAR *start = add; //コピー先確保 UCHAR *seek = start; int cl_num = dir->head_cluster; int limit = dir->size / CLUSTER_SIZE + (dir->size % CLUSTER_SIZE==0?0:1); int cnt=1; if(start == 0)return 0;//mallocできなかった while(cl_num != 0xfff){ if(cnt==INF)return 0;//FATがうまく読めてない //最後のあまりをコピー if(cnt==limit){ kmemcpy(seek,getClusterAdd(cl_num),dir->size%CLUSTER_SIZE); break; } kmemcpy(seek,getClusterAdd(cl_num),CLUSTER_SIZE); cl_num = getNextCluster(cl_num); seek += CLUSTER_SIZE; cnt++; } return start; }
/** * Creates a file (creates the directory entry for a file) for optimized write. * After this function returns successfully, it should be possible to do optimized * writes on the file starting at the beginning. * No checks are done against duplicate file name, and no clusters are allocated. * File space is allocated during write operations. * * @param[in] fs Filesystem structure. * @param[in] dir Directory structure. * @param[out] fileOpt Output optimized file structure. * @param[in] name File name, up to 8 characters. * @param[in] ext File extension, up to 3 characters. * @retval 1 Success * @retval -1 Error creating file * @retval -2 SD Card Error * @retval -128 General error */ int8_t FAT32_CreateFileOpt(FAT32FS *fs, FAT32Directory *dir, FAT32FileOpt *file, char *name, char *ext) { uint32_t currentCluster = dir->directoryTableAvailableCluster; fs_addr_t currentLBA = dir->directoryTableAvailableLBA; uint8_t clusterOffset = dir->directoryTableAvailableClusterOffset; // block number within the cluster fs_length_t iii = 0; DBG_DATA_printf("Starting cluster = 0x%08lx", currentCluster); // Search for an empty file while (1) { if (BLOCK_SIZE != SD_SPI_ReadSingleBlock(fs->card, currentLBA, file->directoryTableBlockData)) { DBG_printf("Error creating file (SD Read error on LBA = 0x%08lx).", currentLBA); return -2; // Sanity check: Not reading the correct number of bytes } DBG_DATA_printf("Read Directory Table LBA = 0x%08lx", currentLBA) // Search Directory Table for desired entry for (iii = 0; iii < fs->bytesPerSector; iii += 32) { DBG_SPAM_printf("Searching record '%8.8s.%3.3s'.", file->directoryTableBlockData + iii, file->directoryTableBlockData + iii + 8); if (file->directoryTableBlockData[iii] == 0x00 || file->directoryTableBlockData[iii] == 0xe5) { // Available entry DBG_printf("Available entry found."); // Update directory structure with new end dir->directoryTableAvailableCluster = currentCluster; dir->directoryTableAvailableClusterOffset = clusterOffset; dir->directoryTableAvailableLBA = currentLBA; FATCreateDirectoryTableEntry(file->directoryTableBlockData+iii, name, ext); // Fill out file structure strncpy((char *) file->name, (char*)file->directoryTableBlockData+iii, 8); strncpy((char *) file->ext, (char*)file->directoryTableBlockData+iii+8, 3); file->fs = fs; file->directoryTableLBA = currentLBA; file->directoryTableBlockOffset = iii; file->directoryTableDirty = 0; file->startCluster = 0; file->size = 0; file->previousFATBlockData = file->previousFATData; file->currentFATBlockData = file->currentFATData; file->previousFATBlockOffset = 0; file->previousFATDirty = 0; file->previousFileSize = 0; file->currentCluster = 0; file->currentLBA = 0; file->position = 0; file->currentOperation = FILE_OP_None; file->nextOperation = FILE_OP_WritingDataIdle; file->dataBuffer[0] = SD_DMA_GetBuffer(0); if (file->dataBuffer[0] == NULL) { DBG_ERR_printf("Error allocating DMA buffer 0"); return -128; } file->dataBuffer[1] = SD_DMA_GetBuffer(1); if (file->dataBuffer[1] == NULL) { DBG_ERR_printf("Error allocating DMA buffer 1"); return -128; } file->fsBuffer = SD_DMA_GetBuffer(2); if (file->fs == NULL) { DBG_ERR_printf("Error allocating DMA FS buffer"); return -128; } file->dataBufferWrite = 0; file->dataBufferFill = 0; file->dataBufferNumFilled = 0; file->dataBufferPos = 0; file->overflowBufferBegin = 0; file->overflowBufferEnd = 0; file->overflowBufferSize = 0; FAT32_InitializeFileFAT(file); SD_SPI_WriteSingleBlock(fs->card, file->directoryTableLBA, file->directoryTableBlockData); file->directoryTableDirty = 0; SD_SPI_WriteSingleBlock(fs->card, file->currentFATLBA, file->currentFATBlockData); file->currentFATAllocated = 0; FAT32_FillFSInformationSector(file); SD_SPI_WriteSingleBlock(fs->card, fs->FS_info_LBA, file->fsBuffer); file->fs->fsInfoDirty = 0; return 1; } } // Advance to next block clusterOffset++; if (clusterOffset >= fs->sectorsPerCluster) { // End of cluster currentCluster = getNextCluster(fs, currentCluster); DBG_DATA_printf("Next cluster = 0x%08lx", currentCluster); // Sanity check: ensure Directory Table cluster is valid if (currentCluster >= 0xF0000000) { DBG_printf("Error creating file (searched past end of Directory Table Cluster)."); return -1; } currentLBA = GetClusterLBA(fs, currentCluster); clusterOffset = 0; } else { // Advance to next block within cluster currentLBA++; } } }
void listfiles(struct BootEntry* b,char* diskpath,char* lpath) { //find the sector num of root directory unsigned int rootcluster = b->BPB_RootClus; unsigned int rootsectornum = b->BPB_RsvdSecCnt + b->BPB_NumFATs * b->BPB_FATSz32 + rootcluster -2; unsigned int rootaddress = rootsectornum * b->BPB_BytsPerSec; //Now you know the address, first read directory Entries //Here, i represents layer. int i=1; unsigned int currentcluster =rootcluster; //we need address for the starting point of the folder unsigned int address = rootaddress; unsigned int current_address; //start with root current_address = lseek(devicefd, rootaddress, SEEK_SET); //find the directory while(tokens[i-1][0]!='\0'){ //assume you have reached layer i-1. Start with layer 0, i.e. root //so, try to match tokens[i-1] in the directory tokens[i-2]. Or -1 as root. strcat(tokens[i-1],"/"); while(1) { struct DirEntry *entry = malloc(sizeof(struct DirEntry)); //read the device entry and advance. read(devicefd, entry, sizeof(struct DirEntry)); current_address = lseek(devicefd, 0,SEEK_CUR); if(current_address>(cluster_to_address(currentcluster+1))) { //look for next cluster. go to fat table. currentcluster = getNextCluster(currentcluster); read(devicefd, entry, sizeof(struct DirEntry)); } //check if it is LNF while(entry->DIR_Attr == 0x0f) { read(devicefd, entry, sizeof(struct DirEntry)); if(current_address>cluster_to_address(currentcluster+1)) { currentcluster = getNextCluster(currentcluster); read(devicefd, entry, sizeof(struct DirEntry)); //look for next cluster. go to fat table. } } //check if it is directory if(entry->DIR_Attr != 0x10) { free(entry); continue; } //now, time to test name! char *name = getName(entry->DIR_Name,entry->DIR_Attr); //check if you got it if(strcmp(name,tokens[i-1])==0) { //got it. Now, seek to that place currentcluster = get_cluster_from_directory_entry(entry); current_address = cluster_to_address(currentcluster); lseek(devicefd,current_address,SEEK_SET); free(entry); free(name); break; } free(entry); free(name); } //in root, find that one // printf("tokens[%d]: %s\n",i-1,tokens[i-1]); i++; } //Now you have found the place to start searching int count = 1; while(1) { //allocate new directory entry struct DirEntry *entry = malloc(sizeof(struct DirEntry)); //read the device entry and advance. read(devicefd, entry, sizeof(struct DirEntry)); current_address = lseek(devicefd, 0,SEEK_CUR); if(current_address>(cluster_to_address(currentcluster+1))) { //look for next cluster. go to fat table. currentcluster = getNextCluster(currentcluster); if(currentcluster == -1) exit(EXIT_SUCCESS); read(devicefd, entry, sizeof(struct DirEntry)); } if(entry->DIR_Attr == 0x00) { break; } //check if it is LNF while(entry->DIR_Attr == 0x0f) { read(devicefd, entry, sizeof(struct DirEntry)); if(current_address>cluster_to_address(currentcluster+1)) { currentcluster = getNextCluster(currentcluster); if(currentcluster == -1) exit(EXIT_SUCCESS); read(devicefd, entry, sizeof(struct DirEntry)); //look for next cluster. go to fat table. } } //now, we reach the normal portion //here, a is the address of cluster //starting cluster num long unsigned int starting_cluster = get_cluster_from_directory_entry(entry); char *name = getName(entry->DIR_Name,entry->DIR_Attr); //order, name, file size, starting cluster printf("%d, %s, %lu, %ld\n", count, name, entry->DIR_FileSize, starting_cluster); count++; //lseek(devicefd, 32, SEEK_CUR); free(name); free(entry); } close(devicefd); }
void recoverfiles(char* r_targetpath,char* o_outputpath,struct BootEntry* b) { //find the sector num of root directory unsigned long filesize = -1; unsigned int rootcluster = b->BPB_RootClus; unsigned int rootsectornum = b->BPB_RsvdSecCnt + b->BPB_NumFATs * b->BPB_FATSz32 + rootcluster -2; unsigned int rootaddress = rootsectornum * b->BPB_BytsPerSec; //Now you know the address, first read directory Entries //Here, i represents layer. int i=1; unsigned int currentcluster =rootcluster; //we need address for the starting point of the folder unsigned int address = rootaddress; unsigned int current_address; //start with root current_address = lseek(devicefd, rootaddress, SEEK_SET); //find the directory //use i, but not i-1. Assures find the one before file while(rtokens[i][0]!='\0') { //assume you have reached layer i-1. Start with layer 0, i.e. root //so, try to match tokens[i-1] in the directory tokens[i-2]. Or -1 as root. strcat(rtokens[i-1],"/"); while(1) { struct DirEntry *entry = malloc(sizeof(struct DirEntry)); //read the device entry and advance. read(devicefd, entry, sizeof(struct DirEntry)); current_address = lseek(devicefd, 0,SEEK_CUR); if(current_address>(cluster_to_address(currentcluster+1))) { //look for next cluster. go to fat table. currentcluster = getNextCluster(currentcluster); read(devicefd, entry, sizeof(struct DirEntry)); } //check if it is LNF while(entry->DIR_Attr == 0x0f) { read(devicefd, entry, sizeof(struct DirEntry)); if(current_address>cluster_to_address(currentcluster+1)) { currentcluster = getNextCluster(currentcluster); read(devicefd, entry, sizeof(struct DirEntry)); //look for next cluster. go to fat table. } } //check if it is directory if(entry->DIR_Attr != 0x10) { free(entry); continue; } //now, time to test name! char *name = getName(entry->DIR_Name,entry->DIR_Attr); //check if you got it. if(strcmp(name,rtokens[i-1])==0) { //got it. Now, seek to that place currentcluster = get_cluster_from_directory_entry(entry); current_address = cluster_to_address(currentcluster); lseek(devicefd,current_address,SEEK_SET); free(entry); free(name); break; } free(entry); free(name); } //in root, find that one i++; } //Now, you have reached the directory set containing the file. Search in this directory to get the file. char copy_of_file[1024]; strcpy(copy_of_file, rtokens[i-1]); copy_of_file[0] = '?'; int emptyflag = 0; //printf("%s\n",rtokens[i-1]); while(1) { struct DirEntry *entry = malloc(sizeof(struct DirEntry)); //read the device entry and advance. read(devicefd, entry, sizeof(struct DirEntry)); current_address = lseek(devicefd, 0,SEEK_CUR); if(current_address>(cluster_to_address(currentcluster+1))) { //look for next cluster. go to fat table. currentcluster = getNextCluster(currentcluster); if(currentcluster == -1) { printf("%s: error - file not found\n",rtokens[i-1]); exit(EXIT_FAILURE); } read(devicefd, entry, sizeof(struct DirEntry)); } //check if it is LNF while(entry->DIR_Attr == 0x0f) { read(devicefd, entry, sizeof(struct DirEntry)); if(current_address>cluster_to_address(currentcluster+1)) { currentcluster = getNextCluster(currentcluster); if(currentcluster == -1) { printf("%s: error - file not found\n",rtokens[i-1]); exit(EXIT_FAILURE); } read(devicefd, entry, sizeof(struct DirEntry)); //look for next cluster. go to fat table. } } //check if it is directory. If yes, skip it. We want file. if(entry->DIR_Attr == 0x10) { free(entry); continue; } //now, time to test name! char *name = getName(entry->DIR_Name,entry->DIR_Attr); //check if you got it. if(strcmp(name,copy_of_file)==0) { //got it. Now, seek to that place currentcluster = get_cluster_from_directory_entry(entry); current_address = cluster_to_address(currentcluster); //check if file is empty if((currentcluster!=0)&&(checkCurrentCluster(currentcluster)!=0)) { printf("%s: error - fail to recover\n",rtokens[i-1]); exit(EXIT_FAILURE); } if(currentcluster == 0) { emptyflag = 1; } printf("%s: recovered\n",rtokens[i-1]); filesize = entry->DIR_FileSize; printf("file size:%lu\n",filesize); lseek(devicefd,current_address,SEEK_SET); free(entry); free(name); break; } free(entry); free(name); } //Now, you are at the file cluster. Do recovery! FILE *out =NULL; char buf[filesize]; //if not able to open if(!(out=fopen(o_outputpath,"w+"))) { printf("%s: failed to open\n",rtokens[i-1]); exit(EXIT_FAILURE); } //Copy the Content to the file //write one by one read(devicefd, buf,filesize); fwrite(buf,1,filesize,out); fclose(out); exit(EXIT_SUCCESS); }