/** * Prepends a path to our path, unless our path is an an absolute path. * * @param path the path to prepend */ void Filename::prependPath(const Filename &path) { if (m_path.size() != 0 && m_path[0] != PATH_SEPARATOR) { m_path = path.getPath() + m_path; convertToSystemPath(m_path); makeFullPath(); } } // Filename::prependPath
/** * Sets the drive letter of the file name. * * @param drive the drive */ void Filename::setDrive(const char *drive) { if (drive != NULL && isalpha(*drive)) m_drive = std::string(drive, 1) + ":"; else m_drive = ""; makeFullPath(); } // Filename::setDrive
void makeSabun(char *sabunFile, char *beforeDir, char *afterDir, int correctAddDelete) { char *dir1 = beforeDir; char *dir2 = afterDir; autoList_t *files1; autoList_t *files2; autoList_t *mfiles; autoList_t *trailLines = newList(); char *file; char *line; uint index; FILE *fp; // check no dirs. { autoList_t *dirs1 = lsDirs(dir1); autoList_t *dirs2 = lsDirs(dir2); errorCase(getCount(dirs1) || getCount(dirs2)); releaseAutoList(dirs1); releaseAutoList(dirs2); } files1 = lsFiles(dir1); files2 = lsFiles(dir2); dir1 = makeFullPath(dir1); dir2 = makeFullPath(dir2); changeRoots(files1, dir1, NULL); changeRoots(files2, dir2, NULL); fp = fileOpen(sabunFile, "wb"); writeLine(fp, FILEHDR_SIGNATURE); rapidSortLines(files1); rapidSortLines(files2); addCwd(dir1); foreach(files1, file, index) // 更新前のファイルとハッシュ、確認用 { writeLine(fp, file); writeLine_x(fp, md5_makeHexHashFile(file)); }
/** * Appends a path to our path. If the path is an absolute path, replaces our path. * * @param path the path to append */ void Filename::appendPath(const Filename &path) { std::string localpath = path.getPath(); convertToSystemPath(localpath); if (localpath.size() != 0 && localpath[0] == PATH_SEPARATOR) m_path = localpath; else m_path += localpath; makeFullPath(); } // Filename::appendPath
void convertFieldData( char *indir, char *outdir, int pjid ) { char outpath[400]; snprintf(outpath, sizeof(outpath), "field_data_%d_%d_%d_%d", pjid, FIELD_W, FIELD_H, (int)sizeof(Cell) ); assertmsg( sizeof(Cell) == 48, "invalid Cell size compiled:%d. Expect 48. incorrect version?", sizeof(Cell) ); char outfullpath[400]; makeFullPath( outdir, outfullpath, sizeof(outfullpath), outpath ); if( fileExist(outfullpath) ) { print("FATAL: File exists:'%s'", outfullpath); return; } size_t read_total = 0; int chw = FIELD_W / CHUNKSZ; int chh = FIELD_H / CHUNKSZ; for(int chy=0;chy<chh;chy++) { for( int chx=0;chx<chw;chx++) { char path[400]; snprintf( path, sizeof(path), "field_data_%d_%d_%d_%d_%d", pjid, chx*CHUNKSZ, chy*CHUNKSZ, CHUNKSZ, CHUNKSZ ); char fullpath[400]; makeFullPath( indir, fullpath, sizeof(fullpath), path ); char buf[32*1024]; size_t sz = sizeof(buf); bool res = readFile( fullpath, buf, &sz ); assertmsg( res, "can't read file:'%s'", fullpath); if(chx%8==0)prt("."); read_total += sz; if( chx==chw-1 ) print("chunk y:%d total:%d",chy, read_total ); assertmsg( sz < sizeof(buf), "saved file is too large:'%s'", fullpath ); char decompressed[sizeof(Cell)*CHUNKSZ*CHUNKSZ]; int decomplen = memDecompressSnappy( decompressed, sizeof(decompressed), buf, sz ); assertmsg(decomplen == sizeof(decompressed), "invalid decompressed size:%d file:'%s'", decomplen, fullpath ); int chunk_index = chx + chy*chw; size_t offset = chunk_index * sizeof(Cell)*CHUNKSZ*CHUNKSZ; // print("write. ofs:%d chx:%d chy:%d", offset, chx, chy ); res = writeFileOffset( outfullpath, decompressed, decomplen, offset, false ); assertmsg(res, "writeFileOffset failed for '%s'", outfullpath ); } } }
/** * Sets the name of the file name. * If the name has an extension, the extension will be set * If the name has a full path (starts with drive or separator), the path will be set * If the name has a relative path, the path will be appended to the current path * * @param name the name */ void Filename::setName(const char *name) { if (name == NULL || *name == '\0') m_name = ""; else { #ifdef WIN32 if (isalpha(*name) && *(name + 1) == ':') { setDrive(name); name += 2; } #endif std::string localname = name; convertToSystemPath(localname); const char *dot = strrchr(localname.c_str(), '.'); const char *firstSeparator = strchr(localname.c_str(), PATH_SEPARATOR); const char *lastSeparator = strrchr(localname.c_str(), PATH_SEPARATOR); if (firstSeparator != NULL) { // name has a path if (firstSeparator == localname) { // set path m_path = std::string(firstSeparator, lastSeparator - firstSeparator + 1); } else { // append path m_path += std::string(localname.c_str(), lastSeparator - localname.c_str() + 1); } } if (dot != NULL && (lastSeparator == NULL || dot > lastSeparator)) { // name has an extension setExtension(dot); if (lastSeparator == NULL) m_name = std::string(localname.c_str(), dot - localname.c_str()); else m_name = std::string(lastSeparator + 1, dot - (lastSeparator + 1)); } else { // name doesn't have an extension if (lastSeparator == NULL) m_name = localname; else m_name = std::string(lastSeparator + 1); } } makeFullPath(); } // Filename::setName
// public static bool Path::isParentPath (const String& path1, const String& path2) { String tmp1 = path1; String tmp2 = path2; String realPath1 = makeFullPath (tmp1.trim ()); String realPath2 = makeFullPath (tmp2.trim ()); if (isSeparator (realPath1 [(int) realPath1.getLength () - 1]) == false) realPath1 += Path::separator; if (isSeparator (realPath2 [(int) realPath2.getLength () - 1]) == false) realPath2 += Path::separator; #ifdef __WINDOWS__ if (realPath2.compareIgnoreCase (realPath1) == 1) return false; realPath1.toLower (); realPath2.toLower (); if (realPath2.find (realPath1) == 0) return true; else return false; #else if (realPath2.compare (realPath1) == 0) return false; else if (realPath2.find (realPath1) == 0) return true; else return false; #endif }
// import - prints the preamble, then loops over all files and import them one by one void SpectraSTMs2LibImporter::import() { for (vector<string>::iterator i = m_impFileNames.begin(); i != m_impFileNames.end(); i++) { string fullName(*i); makeFullPath(fullName); string quoted("\"" + fullName + "\""); string desc = m_params.constructDescrStr(quoted, ".ms2"); m_preamble.push_back(desc); } m_lib->writePreamble(m_preamble); for (vector<string>::iterator i = m_impFileNames.begin(); i != m_impFileNames.end(); i++) { readFromFile(*i); } }
/** * @brief Database::save * @return */ bool Database::save() const { if (!QDir(m_Path).exists()) if (!QDir().mkpath(m_Path)) return false; QFile f(makeFullPath()); if (f.open(QIODevice::WriteOnly)) { QJsonDocument jdoc(toJson()); QTextStream stream(&f); stream << jdoc.toJson(); return true; } return false; }
// 'Corrects' the security on a file by taking ownership of it and giving the current user full control // For directories these will do a complete recursive correction. static void CorrectSecurity(TCHAR *f, DWORD attrib, BOOL takeownership, PSID sid, PACL acl, BOOL oneVolumeOnly) { BY_HANDLE_FILE_INFORMATION info; if (attrib != INVALID_FILE_ATTRIBUTES) { DWORD err; if (sid && takeownership) { err = SetNamedSecurityInfo(f, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, sid, NULL, NULL, NULL); if (err != ERROR_SUCCESS) { LogFileError(TEXT("SetNamedSecurityInfo (change owner)"), f, err); } } if (sid && acl) { err = SetNamedSecurityInfo(f, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, acl, NULL); if (err != ERROR_SUCCESS) { LogFileError(TEXT("SetNamedSecurityInfo (change DACL)"), f, err); } } if ((attrib & FILE_ATTRIBUTE_DIRECTORY) && !(oneVolumeOnly && FileChangesVolume(f))) { // Recursively go through the directories WIN32_FIND_DATA ffd; TCHAR full[BIG_PATH+5], *file = copyStr(f); HANDLE hFind; DWORD dwError; DWORD len = _tcslen(file); while (len > 0 && file[len-1] == L'\\') file[--len] = 0; file[len ] = TEXT('\\'); file[len+1] = TEXT('*'); file[len+2] = 0; hFind = FindFirstFileEx(file, FindExInfoBasic, &ffd, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH); if (hFind == INVALID_HANDLE_VALUE) { dwError = GetLastError(); if (dwError != ERROR_FILE_NOT_FOUND && dwError != ERROR_ACCESS_DENIED) LogFileError(TEXT("FindFirstFileEx in CorrectSecurity failed for"), file, dwError); } else { do { if (_tcscmp(ffd.cFileName, TEXT("..")) == 0 || _tcscmp(ffd.cFileName, TEXT(".")) == 0) continue; CorrectSecurity(makeFullPath(f, ffd.cFileName, full), ffd.dwFileAttributes, takeownership, sid, acl, oneVolumeOnly); } while (FindNextFile(hFind, &ffd) != 0); dwError = GetLastError(); if (dwError != ERROR_NO_MORE_FILES) LogError(TEXT("FindNextFile in CorrectSecurity"), dwError); FindClose(hFind); } free(file); } if (attrib & FILE_ATTRIBUTE_READONLY) { // Remove the read-only attribute SetFileAttributes(f, attrib&!FILE_ATTRIBUTE_READONLY); } } }
/** * Sets the extension of the file name. * * @param path the path */ void Filename::setExtension(const char *extension) { if (extension == NULL || *extension == '\0') m_extension = ""; else { if (*extension == '.') m_extension = extension; else { m_extension = "."; m_extension += extension; } } makeFullPath(); } // Filename::setExtension
/** * @brief Database::load * @param errorList */ void Database::load(ErrorList &errorList) { QFile f(makeFullPath()); if (f.open(QIODevice::ReadOnly)) { QJsonParseError errorMessage; QJsonDocument jdoc(QJsonDocument::fromJson(f.readAll(), &errorMessage)); if (errorMessage.error == QJsonParseError::NoError) { fromJson(jdoc.object(), errorList); } else { errorList << errorMessage.errorString(); } } else { errorList << QObject::tr("Can't load database: %1.").arg(f.fileName()); } m_Valid = errorList.isEmpty(); }
static void ShowBuildTime(char *trgPath) { trgPath = makeFullPath(trgPath); if(existDir(trgPath)) { autoList_t *paths = lss(trgPath); char *path; uint index; sortJLinesICase(paths); foreach(paths, path, index) { char *relPath = changeRoot(strx(path), trgPath, NULL); if(existDir(path)) { cout("------------------------ %s\n", relPath); } else if( !_stricmp("exe", getExt(path)) || !_stricmp("dll", getExt(path)) || !_stricmp("exe_", getExt(path)) || !_stricmp("dll_", getExt(path)) ) { ShowBuildTime_File(path, relPath); } else { char *hash = md5_makeHexHashFile(path); hash[16] = '\0'; cout(" %s %s\n", hash, relPath); memFree(hash); } memFree(relPath); } releaseDim(paths, 1); }
static void AntiSVN(char *targetDir) { targetDir = makeFullPath(targetDir); if(!ForceMode) { cout("%s\n", targetDir); cout("ANTI-SVN PROCEED? [Any/ESC]\n"); if(clearGetKey() == 0x1b) termination(1); cout("GO!\n"); } for(; ; ) { autoList_t *dirs = lssDirs(targetDir); char *dir; uint index; int found = 0; foreach(dirs, dir, index) { if( !_stricmp(".svn", getLocal(dir)) || !_stricmp("_svn", getLocal(dir)) ) { coExecute_x(xcout("RD /S /Q \"%s\"", dir)); found = 1; } } releaseDim(dirs, 1); if(!found) break; coSleep(1000); } memFree(targetDir); }
/** * Sets the path of the file name. * If the path has a drive letter, the drive will be set (Winodws only) * * @param path the path */ void Filename::setPath(const char *path) { if (path == NULL || *path == '\0') m_path = ""; else { #ifdef WIN32 if (isalpha(*path) && *(path + 1) == ':') { setDrive(path); path += 2; } #endif m_path = path; convertToSystemPath(m_path); if (m_path[strlen(path) - 1] != PATH_SEPARATOR) m_path += PATH_SEPARATOR; } makeFullPath(); } // Filename::setPath
bool ConfigTree::deleteParam( const std::string ¶mPath, const std::string ¶mName ) { CONFIGSYS_DEBUG_CALLS; std::string fullPath = makeFullPath(paramPath); try { // get the parent node ptree paramParent = _treeRoot.get_child(fullPath); // Delete the parameter. // (Note: Only erases 'direct children'. // i.e. paramParent.erase("myname") might erase something, // but paramParent.erase("my.name") will never erase anything). int del_n = paramParent.erase(paramName); if(del_n == 0) { std::cout << "ConfigTree::deleteParam(...): Nothing to erase" << " (there's no '" << paramName << "' at the given path)." << std::endl; return false; // return failure if nothing was erased } // put back the modified parent node _treeRoot.put_child(fullPath, paramParent); } catch (boost::property_tree::ptree_error e) { std::cout << "ConfigTree::deleteParam(...): ACCESS ERROR:" << e.what() << std::endl; return false; } return true; }
int InputFile::load(const std::string& fpath){ // Get full path fullpath = fpath; if(!makeFullPath(fullpath)) return InputFile::INVALID_PATH; // Open file FILE* fp=fopen(fpath.c_str(),"rb"); // Check is file opened properly if(fp==NULL) return InputFile::FAILED_TO_OPEN; // Check size fseek(fp, 0, SEEK_END); long fp_size = ftell(fp); fseek(fp, 0, SEEK_SET); if(fp_size == -1L) return InputFile::FAILED_TO_READ; // Read char* data = new char[fp_size]; fread(data, 1, fp_size, fp); if (data == NULL) return InputFile::FAILED_TO_READ; // Close fclose(fp); // Copy to contents this->contents = std::string(data); delete[] data; // Success! return SUCCESS; }
/* handle a command, return code is 0 if the command was (at least partially) valid, -1 for quitting, -2 for if invalid -3 if empty. */ int doCommand( char *cmdToken[] ) { if ( strcmp( cmdToken[0], "help" ) == 0 || strcmp( cmdToken[0], "h" ) == 0 ) { usage( cmdToken[1] ); return 0; } if ( strcmp( cmdToken[0], "quit" ) == 0 || strcmp( cmdToken[0], "q" ) == 0 ) { return -1; } if ( strcmp( cmdToken[0], "create" ) == 0 || strcmp( cmdToken[0], "make" ) == 0 || strcmp( cmdToken[0], "mk" ) == 0 ) { static char myTicket[30]; char *fullPath = 0; if ( strlen( cmdToken[3] ) > 0 ) { strncpy( myTicket, cmdToken[3], 30 ); } else { makeTicket( myTicket ); } makeFullPath( cmdToken[2], &fullPath ); doTicketOp( "create", myTicket, cmdToken[1], fullPath, cmdToken[3] ); return 0; } if ( strcmp( cmdToken[0], "delete" ) == 0 ) { doTicketOp( "delete", cmdToken[1], cmdToken[2], cmdToken[3], cmdToken[4] ); return 0; } if ( strcmp( cmdToken[0], "mod" ) == 0 ) { doTicketOp( "mod", cmdToken[1], cmdToken[2], cmdToken[3], cmdToken[4] ); return 0; } if ( strcmp( cmdToken[0], "ls" ) == 0 ) { showTickets( cmdToken[1] ); return 0; } if ( strcmp( cmdToken[0], "ls-all" ) == 0 ) { printf( "Listing all of your tickets, even those for which the target collection\nor data-object no longer exists:\n" ); showTickets1( "basic", "" ); return 0; } if ( *cmdToken[0] != '\0' ) { printf( "unrecognized command, try 'help'\n" ); return -2; } return -3; }
/** * @brief Database::fullPath * @return */ QString Database::fullPath() const { return makeFullPath(); }
S32 TorqueMain( S32 argc, const char **argv ) { S32 failed = 0; // Initialize the subsystems. StandardMainLoop::init(); Con::setVariable( "Con::Prompt", "" ); WindowsConsole->enable( true ); // install all drives for now until we have everything using the volume stuff Platform::FS::InstallFileSystems(); Platform::FS::MountDefaults(); bool compatMode = false; bool diffuseNames = false; bool verbose = false; bool saveDTS = true; bool saveDSQ = false; bool genMaterials = false; Torque::Path cfgPath, srcPath, destPath; // Parse arguments S32 i; for ( i = 1; i < argc-1; i++ ) { if ( dStrEqual( argv[i], "--config" ) ) cfgPath = makeFullPath( argv[++i] ); else if ( dStrEqual( argv[i], "--output" ) ) destPath = makeFullPath( argv[++i] ); else if ( dStrEqual( argv[i], "--dsq" ) ) saveDSQ = true; else if ( dStrEqual( argv[i], "--dsq-only" ) ) { saveDTS = false; saveDSQ = true; } else if ( dStrEqual( argv[i], "--compat" ) ) compatMode = true; else if ( dStrEqual( argv[i], "--diffuse" ) ) diffuseNames = true; else if ( dStrEqual( argv[i], "--materials" ) ) genMaterials = true; else if ( dStrEqual( argv[i], "--verbose" ) ) verbose = true; } if ( ( i >= argc ) || ( !dStrEndsWith(argv[i], ".dae") && !dStrEndsWith(argv[i], ".kmz" ) ) ) { Con::errorf( "Error: no DAE file specified.\n" ); printUsage(); return -1; } srcPath = makeFullPath( argv[i] ); if ( destPath.isEmpty() ) { destPath = srcPath; destPath.setExtension( "dts" ); } if ( !cfgPath.isEmpty() ) Con::printf( "Configuration files not yet supported.\n" ); // Define script callbacks if ( verbose ) Con::evaluate( "function UpdateTSShapeLoadProgress(%progress, %msg) { echo(%msg); }" ); else Con::evaluate( "function UpdateTSShapeLoadProgress(%progress, %msg) { }" ); if ( verbose ) Con::printf( "Parsing configuration file...\n" ); // Set import options ColladaUtils::getOptions().reset(); ColladaUtils::getOptions().forceUpdateMaterials = genMaterials; ColladaUtils::getOptions().useDiffuseNames = diffuseNames; if ( verbose ) Con::printf( "Reading dae file...\n" ); // Attempt to load the DAE file Resource<TSShape> shape = ResourceManager::get().load( srcPath ); if ( !shape ) { Con::errorf( "Failed to convert DAE file: %s\n", srcPath.getFullPath() ); failed = 1; } else { if ( compatMode && !shape->canWriteOldFormat() ) { Con::errorf( "Warning: Attempting to save to DTS v24 but the shape " "contains v26 features. Resulting DTS file may not be valid." ); } FileStream outStream; if ( saveDSQ ) { Torque::Path dsqPath( destPath ); dsqPath.setExtension( "dsq" ); for ( S32 i = 0; i < shape->sequences.size(); i++ ) { const String& seqName = shape->getName( shape->sequences[i].nameIndex ); if ( verbose ) Con::printf( "Writing DSQ file for sequence '%s'...\n", seqName.c_str() ); dsqPath.setFileName( destPath.getFileName() + "_" + seqName ); if ( outStream.open( dsqPath, Torque::FS::File::Write ) ) { shape->exportSequence( &outStream, shape->sequences[i], compatMode ); outStream.close(); } else { Con::errorf( "Failed to save sequence to %s\n", dsqPath.getFullPath().c_str() ); failed = 1; } } } if ( saveDTS ) { if ( verbose ) Con::printf( "Writing DTS file...\n" ); if ( outStream.open( destPath, Torque::FS::File::Write ) ) { if ( saveDSQ ) shape->sequences.setSize(0); shape->write( &outStream, compatMode ); outStream.close(); } else { Con::errorf( "Failed to save shape to %s\n", destPath.getFullPath().c_str() ); failed = 1; } } } // Clean everything up. StandardMainLoop::shutdown(); // Do we need to restart? if( StandardMainLoop::requiresRestart() ) Platform::restartInstance(); return failed; }
// Finds files recursively // Committed is if the current recursive path only contains files to be deleted (and thus simply list all files found) // Otherwise wildcards are examined and directories are recursed static void FindFiles(TCHAR *path, BOOL committed, BOOL oneVolumeOnly) { WIN32_FIND_DATA ffd; BY_HANDLE_FILE_INFORMATION info; TCHAR full[BIG_PATH+5]; HANDLE hFind; DWORD dwError, attrib; TCHAR *file, *base; BOOL match_all; set *matches = NULL; DWORD len = _tcslen(path); while (len > 0 && path[len-1] == L'\\') path[--len] = 0; file = copyStr(path); attrib = GetFileAttributes(path); match_all = attrib != INVALID_FILE_ATTRIBUTES && ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); if (match_all) { committed = TRUE; file[len ] = TEXT('\\'); file[len+1] = TEXT('*'); file[len+2] = 0; } else { file[len] = 0; } base = getBaseDirectory(file); if (!committed) matches = set_create((compare_func)&_tcscmp); // first pass we match the pattern only and everything we find is committed hFind = FindFirstFileEx(file, FindExInfoBasic, &ffd, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH); if (hFind == INVALID_HANDLE_VALUE) { dwError = GetLastError(); if (dwError != ERROR_FILE_NOT_FOUND && dwError != ERROR_ACCESS_DENIED) LogFileError(TEXT("FindFirstFileEx in FindFiles failed for"), file, dwError); } else { do { if (_tcscmp(ffd.cFileName, TEXT("..")) == 0 || _tcscmp(ffd.cFileName, TEXT(".")) == 0) continue; makeFullPath(base, ffd.cFileName, full); vector_append(files, copyStr(full)); if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !(oneVolumeOnly && (ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && FileChangesVolume(full))) { if (!committed) set_insert(matches, copyStr(ffd.cFileName)); FindFiles(full, TRUE, oneVolumeOnly); } } while (FindNextFile(hFind, &ffd) != 0); dwError = GetLastError(); if (dwError != ERROR_NO_MORE_FILES) LogError(TEXT("FindNextFile in FindFiles"), dwError); FindClose(hFind); } if (!committed) { // second pass we are just looking for directories to recurse into // if we are already committed then there is no need to do this as all directories and files will be enumerated above TCHAR *pattern = getFileName(file); TCHAR *baseSrch = copyStr(base); len = _tcslen(base); baseSrch[len ] = L'\\'; baseSrch[len+1] = L'*'; baseSrch[len+2] = 0; hFind = FindFirstFileEx(baseSrch, FindExInfoBasic, &ffd, FindExSearchLimitToDirectories, NULL, FIND_FIRST_EX_LARGE_FETCH); if (hFind == INVALID_HANDLE_VALUE) { dwError = GetLastError(); if (dwError != ERROR_FILE_NOT_FOUND && dwError != ERROR_ACCESS_DENIED) LogFileError(TEXT("FindFirstFileEx in FindFiles2 failed for"), baseSrch, dwError); } else { do { if (_tcscmp(ffd.cFileName, TEXT("..")) != 0 && _tcscmp(ffd.cFileName, TEXT(".")) != 0 && ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (!set_contains(matches, ffd.cFileName)) { // don't re-recurse into a directory makeFullPath2(base, ffd.cFileName, pattern, full); if (!(oneVolumeOnly && (ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && FileChangesVolume(full))) { FindFiles(full, FALSE, oneVolumeOnly); } } } } while (FindNextFile(hFind, &ffd) != 0); dwError = GetLastError(); if (dwError != ERROR_NO_MORE_FILES) LogError(TEXT("FindNextFile in FindFiles2"), dwError); FindClose(hFind); } free(baseSrch); } free(file); free(base); if (!committed) set_destroy(matches, TRUE); }