/*---------------------------------------------------------------------------*/ static struct file * find_file(const char *name) { int i; struct file_header hdr; coffee_page_t page; /* First check if the file metadata is cached. */ for(i = 0; i < COFFEE_MAX_OPEN_FILES; i++) { if(FILE_FREE(&coffee_files[i])) { continue; } read_header(&hdr, coffee_files[i].page); if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr) && strcmp(name, hdr.name) == 0) { return &coffee_files[i]; } } /* Scan the flash memory sequentially otherwise. */ for(page = 0; page < COFFEE_PAGE_COUNT; page = next_file(page, &hdr)) { read_header(&hdr, page); if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr) && strcmp(name, hdr.name) == 0) { return load_file(page, &hdr); } } return NULL; }
/*---------------------------------------------------------------------------*/ int cfs_readdir(struct cfs_dir *dir, struct cfs_dirent *record) { struct file_header hdr; coffee_page_t page; memcpy(&page, dir->dummy_space, sizeof(coffee_page_t)); while(page < COFFEE_PAGE_COUNT) { read_header(&hdr, page); if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr)) { coffee_page_t next_page; memcpy(record->name, hdr.name, sizeof(record->name)); record->name[sizeof(record->name) - 1] = '\0'; record->size = file_end(page); next_page = next_file(page, &hdr); memcpy(dir->dummy_space, &next_page, sizeof(coffee_page_t)); return 0; } page = next_file(page, &hdr); } return -1; }
/*---------------------------------------------------------------------------*/ static int remove_by_page(coffee_page_t page, int remove_log, int close_fds) { struct file_header hdr; int i; read_header(&hdr, page); if(!HDR_ACTIVE(hdr)) { return -1; } if(remove_log && HDR_MODIFIED(hdr)) { if(remove_by_page(hdr.log_page, 0, 0) < 0) { return -1; } } hdr.flags |= HDR_FLAG_OBSOLETE; write_header(&hdr, page); *gc_wait = 0; /* Close all file descriptors that reference the removed file. */ if(close_fds) { for(i = 0; i < COFFEE_FD_SET_SIZE; i++) { if(coffee_fd_set[i].file != NULL && coffee_fd_set[i].file->page == page) { coffee_fd_set[i].flags = COFFEE_FD_FREE; } } } for(i = 0; i < COFFEE_MAX_OPEN_FILES; i++) { if(coffee_files[i].page == page) { coffee_files[i].page = INVALID_PAGE; coffee_files[i].references = 0; coffee_files[i].max_pages = 0; } } #if !COFFEE_CONF_EXTENDED_WEAR_LEVELLING if(!HDR_LOG(hdr)) { collect_garbage(GC_RELUCTANT); } #endif return 0; }
/*---------------------------------------------------------------------------*/ int cfs_readdir(struct cfs_dir *dir, struct cfs_dirent *record) { struct file_header hdr; coffee_page_t page; for(page = *(coffee_page_t *)dir->dummy_space; page < COFFEE_PAGE_COUNT;) { watchdog_periodic(); read_header(&hdr, page); if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr)) { memcpy(record->name, hdr.name, sizeof(record->name)); record->name[sizeof(record->name) - 1] = '\0'; record->size = file_end(page); *(coffee_page_t *)dir->dummy_space = next_file(page, &hdr); return 0; } page = next_file(page, &hdr); } return -1; }