inline bool list_files(FileInfoContainer &p_infos, const char *p_path) { dir_t _dir = NULL; RETRY_DO { RETRY_LOG("gfs::list_files failed"); _dir = file_system()->opendir(p_path); } RETRY_ON((_dir == NULL) && is_directory(p_path)); if (_dir == NULL) return false; // 注意,如果有. ..的话,要过滤掉 Directory::iterator _iter; file_info _info; while(!_dir->done()) { _iter = _dir->next(); _info.m_name = _iter->name(); _info.m_is_dir = _iter->is_dir(); p_infos.push_back(_info); } file_system()->closedir(_dir); return true; }
std::map<IVolume::ELanguage, std::string> CVolumeWiiCrypted::GetNames(bool prefer_long) const { std::unique_ptr<IFileSystem> file_system(CreateFileSystem(this)); std::vector<u8> opening_bnr(NAMES_TOTAL_BYTES); opening_bnr.resize(file_system->ReadFile("opening.bnr", opening_bnr.data(), opening_bnr.size(), 0x5C)); return ReadWiiNames(opening_bnr); }
inline bool mkdir(const char *p_path) { int32_t ret = 0; RETRY_DO { RETRY_LOG("gfs::mkdir failed"); ret = file_system()->mkdir(p_path); } RETRY_ON((ret < 0) && (! exists(p_path))); return ret == 0; }
inline bool remove(const char *p_path) { int32_t ret = 0; RETRY_DO { RETRY_LOG("gfs::remove failed"); ret = file_system()->unlink(p_path); } RETRY_ON(ret < 0); return ret == 0; }
inline bool exists(const char *p_path) { int32_t ret = 0; RETRY_DO { RETRY_LOG("gfs::exists failed"); ret = file_system()->exists(p_path); } RETRY_ON ((ret != 0) && (ret != 1)); // TODO: 可能这里无限重试更好? return ret == 1; }
inline bool stat(file_status &p_status, const char *p_path) { uint32_t ret = 0; RETRY_DO { RETRY_LOG("gfs::stat failed"); ret = file_system()->stat(p_path, &p_status, true/*get_exact_len*/); } RETRY_ON((ret < 0) && (get_errno() != ERR_NODE_NOEXIST)); return ret == 0; }
inline bool rename(const char *p_old_path, const char *p_new_path) { int32_t ret = 0; RETRY_DO { RETRY_LOG("gfs::rename failed"); ret = file_system()->rename(p_old_path, p_new_path); } RETRY_ON(ret < 0); return ret == 0; }
inline file_t open(const char *p_path, mode_t p_mode = MT_O_RDONLY) { file_t fd = BAD_FILE; RETRY_DO { RETRY_LOG("gfs::open failed"); fd = file_system()->open(p_path, static_cast<int32_t>(p_mode)); } RETRY_ON ((fd == BAD_FILE) && (ERR_EXIST != get_errno())); // 文件已存在错误则不重试 return fd; }
inline file_t create(const char *p_path) { file_t fd = BAD_FILE; RETRY_DO { RETRY_LOG("gfs::create failed"); if(fd != BAD_FILE) { close(fd); } fd = file_system()->creat(p_path); } RETRY_ON ((fd == BAD_FILE) && (! exists(p_path))); // 创建成功后,验证文件是否存在;因为发生过创建 // 成功后,文件不存在的现象。 return fd; }
inline file_t create(const char *p_path, std::size_t replica_number) { file_t fd = BAD_FILE; RETRY_DO { RETRY_LOG("gfs::create failed"); if(fd != BAD_FILE) { close(fd); } fd = file_system()->creat(p_path, static_cast<int32_t>(replica_number)); } RETRY_ON ((fd == BAD_FILE) && (! exists(p_path))); // 创建成功后,验证文件是否存在;因为发生过创建 // 成功后,文件不存在的现象。 return fd; }
bool CVolumeGC::LoadBannerFile() const { // The methods GetNames, GetDescriptions, GetCompany and GetBanner // all need to access the opening.bnr file. These four methods are // typically called after each other, so we store the file in RAM // to avoid reading it from the disc several times. However, // if none of these methods are called, the file is never loaded. if (m_banner_file_type != BANNER_NOT_LOADED) return m_banner_file_type != BANNER_INVALID; std::unique_ptr<IFileSystem> file_system(CreateFileSystem(this)); size_t file_size = (size_t)file_system->GetFileSize("opening.bnr"); if (file_size == BNR1_SIZE || file_size == BNR2_SIZE) { m_banner_file.resize(file_size); file_system->ReadFile("opening.bnr", m_banner_file.data(), m_banner_file.size()); u32 bannerSignature = *(u32*)m_banner_file.data(); switch (bannerSignature) { case 0x31524e42: // "BNR1" m_banner_file_type = BANNER_BNR1; break; case 0x32524e42: // "BNR2" m_banner_file_type = BANNER_BNR2; break; default: m_banner_file_type = BANNER_INVALID; WARN_LOG(DISCIO, "Invalid opening.bnr type"); break; } } else { m_banner_file_type = BANNER_INVALID; WARN_LOG(DISCIO, "Invalid opening.bnr size: %0lx", (unsigned long)file_size); } return m_banner_file_type != BANNER_INVALID; }
void CVolumeGC::LoadBannerFile() const { // If opening.bnr has been loaded already, return immediately if (m_banner_loaded) return; m_banner_loaded = true; GCBanner banner_file; std::unique_ptr<IFileSystem> file_system(CreateFileSystem(this)); size_t file_size = (size_t)file_system->GetFileSize("opening.bnr"); constexpr int BNR1_MAGIC = 0x31524e42; constexpr int BNR2_MAGIC = 0x32524e42; if (file_size != BNR1_SIZE && file_size != BNR2_SIZE) { WARN_LOG(DISCIO, "Invalid opening.bnr. Size: %0zx", file_size); return; } file_system->ReadFile("opening.bnr", reinterpret_cast<u8*>(&banner_file), file_size); bool is_bnr1; if (banner_file.id == BNR1_MAGIC && file_size == BNR1_SIZE) { is_bnr1 = true; } else if (banner_file.id == BNR2_MAGIC && file_size == BNR2_SIZE) { is_bnr1 = false; } else { WARN_LOG(DISCIO, "Invalid opening.bnr. Type: %0x Size: %0zx", banner_file.id, file_size); return; } ExtractBannerInformation(banner_file, is_bnr1); }
Retcode dos_partition(Environ *e, Filesys_action what, Instance *disk, Byte *path, uLong loc, uLong start_unused, uByte *buf, uInt size, uByte *retbuf, uLong *val) { int i, j; Retcode ret = NO_ERROR; int partition = -1; struct bootsector50 *bs = (struct bootsector50*)buf; struct dos_partition part[NDOSPART]; static int indent = 0; DPRINTF(("\ndos_partition: enter\n")); if (size < DOS_BLOCK_SIZE) return E_BLOCKSIZE; /* first see if this is a DOS boot-block */ ret = filesys_read_bytes(e, disk, loc, size, buf); if (ret != NO_ERROR) return ret; DPRINTF(("dos-partition: boot_sect_sig0/1=%#x.%#x jump=%#x" " boot_signature=%#x drive_number=%#x\n", bs->boot_sect_sig[0], bs->boot_sect_sig[1], bs->jump[0], bs->boot_signature, bs->drive_number)); if (bs->boot_sect_sig[0] != BOOTSIG0 || bs->boot_sect_sig[1] != BOOTSIG1 || ((bs->jump[0] == 0xE9 || bs->jump[0] == 0xEB) && bs->boot_signature != 0x29 && bs->boot_signature != 0x13 && bs->boot_signature != 0x7C && bs->boot_signature != 0xBC)) return E_NO_FILESYS; /* copy the partition info */ memcpy((void*)part, buf + DOSPARTOFF, sizeof part); /* see if we have any partitions - may not be a partition table */ for (i = 0; i < 4; i++) { if (part[i].typ != DP_UNUSED) break; } if (i >= 4) return E_NO_FILESYS; if (*path >= '0' && *path <= '3') { partition = *path - '0'; path = strchr(path, ','); if (path == NULL) path = ""; else path++; } else if (*path) { cprintf(e, "dos-partition: unknown partition %s\n", path); return E_ABORT; } if (what == FS_PROBE) strcat((char*)retbuf, ",dos-partition"); for (i = 0; i < 4; i++) { struct dos_partition *p = &part[i]; uInt start, size; /* handle alignment and endian problems */ start = p->start[0] | (p->start[1] << BYTE_SIZE) | (p->start[2] << BYTE_SIZE * 2) | (p->start[3] << BYTE_SIZE * 3); size = p->size[0] | (p->size[1] << BYTE_SIZE) | (p->size[2] << BYTE_SIZE * 2) | (p->size[3] << BYTE_SIZE * 3); DPRINTF(("dos_partition: partition=%d size=%#x start=%#x typ=%#x\n" "\tflag=%#x shd=%#x ssect=%#x scyl=%#x ehd=%#x" " esect=%#x ecyl=%#x\n", i, size, start, p->typ, p->flag, p->shd, p->ssect, p->scyl, p->ehd, p->esect, p->ecyl)); /* find matching fstype */ if (what == FS_LIST && partition < 0) { DPtype *fs; for (fs = g_dplist; fs->name; fs++) if (fs->type == p->typ) break; for (j = 0; j < indent; j++) cprintf(e, " "); cprintf(e, "DOS partition %d: %s (%#x)\n", i, fs->name ? fs->name : "<unknown>", p->typ); } /* make sure we have something in this partition */ if (size == 0 || p->typ == DP_UNUSED) { if (i == partition && what != FS_PROBE) return E_NO_FILESYS; continue; } if (p->typ == DP_EXTENDED) { indent += 4; ret = dos_partition(e, what, disk, path, loc + start * DOS_BLOCK_SIZE, start, buf, DOS_BLOCK_SIZE, retbuf, val); indent -= 4; if (ret != NO_ERROR && ret != E_NO_FILESYS && ret != R_END) return ret; continue; } /* handle filesystems inside our partitions */ switch (what) { case FS_PROBE: ret = file_system(e, what, disk, path, loc + start * DOS_BLOCK_SIZE, start, buf, DOS_BLOCK_SIZE, retbuf, val); if (ret != NO_ERROR && ret != E_NO_FILESYS) return ret; break; case FS_LIST: if (i == partition) { ret = file_system(e, what, disk, path, loc + start * DOS_BLOCK_SIZE, start, buf, DOS_BLOCK_SIZE, retbuf, val); return (ret == E_NO_FILESYS) ? E_UNSUPPORTED_FILESYS : ret; } break; case FS_LOAD: if (i == partition) { if (*path) { ret = file_system(e, what, disk, path, loc + start * DOS_BLOCK_SIZE, start, buf, DOS_BLOCK_SIZE, retbuf, val); return (ret == E_NO_FILESYS) ? E_UNSUPPORTED_FILESYS : ret; } /* no path specified - try to load this partition's bootblock */ return filesys_read_bytes(e, disk, loc + start * DOS_BLOCK_SIZE, *val = DOS_BLOCK_SIZE, retbuf); } else if (i < 0) /* no partition specified - try to load MBR */ return filesys_read_bytes(e, disk, loc * DOS_BLOCK_SIZE, *val = DOS_BLOCK_SIZE, retbuf); break; } } /* no other partitions or filesystems should be on this volume */ DPRINTF(("dos_partition: return R_END\n")); return R_END; }
inline bool close(file_t p_file) { return file_system()->close(p_file) == 0; }