CFileSystem::CFileIter &CWinFileSystem::CWinFileIter::operator ++() { int iRes = _findnexti64(m_hFind, &m_FindData); if (iRes) m_FindData.name[0] = 0; return *this; }
static bool ScanGameDirectory(const char *dir, bool recurse) { guard(ScanGameDirectory); char Path[MAX_PACKAGE_PATH]; bool res = true; // printf("Scan %s\n", dir); #if _WIN32 appSprintf(ARRAY_ARG(Path), "%s/*.*", dir); _finddatai64_t found; long hFind = _findfirsti64(Path, &found); if (hFind == -1) return true; do { if (found.name[0] == '.') continue; // "." or ".." appSprintf(ARRAY_ARG(Path), "%s/%s", dir, found.name); // directory -> recurse if (found.attrib & _A_SUBDIR) { if (recurse) res = ScanGameDirectory(Path, recurse); else res = true; } else res = RegisterGameFile(Path); } while (res && _findnexti64(hFind, &found) != -1); _findclose(hFind); #else DIR *find = opendir(dir); if (!find) return true; struct dirent *ent; while (/*res &&*/ (ent = readdir(find))) { if (ent->d_name[0] == '.') continue; // "." or ".." appSprintf(ARRAY_ARG(Path), "%s/%s", dir, ent->d_name); // directory -> recurse // note: using 'stat64' here because 'stat' ignores large files struct stat64 buf; if (stat64(Path, &buf) < 0) continue; // or break? if (S_ISDIR(buf.st_mode)) { if (recurse) res = ScanGameDirectory(Path, recurse); else res = true; } else res = RegisterGameFile(Path); } closedir(find); #endif return res; unguard; }
/** * Move all files from temp to destination directory if at end of group. * Called recursively to move each file individually. */ void move_files_individual(struct group_list_t *group, const char *local_temp, char *local_dest) { int emptydir; { #ifdef WINDOWS intptr_t ffhandle; struct _finddatai64_t finfo; char dirglob[MAXPATHNAME]; snprintf(dirglob, sizeof(dirglob), "%s%c*", local_temp, PATH_SEP); if ((ffhandle = _findfirsti64(dirglob, &finfo)) == -1) { gsyserror(group, "Failed to open directory %s", dirglob); return; } emptydir = 1; do { if (strcmp(finfo.name, ".") && strcmp(finfo.name, "..")) { emptydir = 0; move_file_individual(group, local_temp, local_dest, finfo.name); } } while (_findnexti64(ffhandle, &finfo) == 0); _findclose(ffhandle); #else DIR *dir; struct dirent *de; if ((dir = opendir(local_temp)) == NULL) { gsyserror(group, "Failed to open directory %s", local_temp); return; } emptydir = 1; // errno needs to be set to 0 before calling readdir, otherwise // we'll report a false error when we exhaust the directory while ((errno = 0, de = readdir(dir)) != NULL) { if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) { emptydir = 0; move_file_individual(group, local_temp, local_dest, de->d_name); } } if (errno && (errno != ENOENT)) { gsyserror(group, "Failed to read directory %s", tempdir); } closedir(dir); #endif } if (emptydir) { run_postreceive(group, local_dest); } if (rmdir(local_temp) == -1) { gsyserror(group, "Failed remove temp directory %s", local_temp); } }
void FileSyst::TransverseDirectory(std::string path, std::vector<directoryvector>& directory) { if ( path.empty() ) return; struct _finddatai64_t data; std::string fname = path + "\\*.*"; try { long h = _findfirsti64(fname.c_str(),&data); if(h >= 0) { directoryvector currentvector; directory.push_back(currentvector); //get iterator to the currentvector element unsigned int currentIndex = directory.size() -1; //Adds the current path to the current vector directory[currentIndex].path = path; do { if( (data.attrib & _A_SUBDIR) ) { // make sure we skip "." and "..". Have to use strcmp here because // some file names can start with a dot, so just testing for the // first dot is not sufficient. if( strcmp(data.name,".") != 0 &&strcmp(data.name,"..") != 0) { // We found a sub-directory, so get the files in it too fname = path + "\\" + data.name; // recursion here! TransverseDirectory(fname, directory); } } else { // this is just a normal filename. So just add it to our vector file newFile = CreateFile(data.name); directory[currentIndex].files.push_back(newFile); } } while( _findnexti64(h,&data) == 0); _findclose(h); } } catch (std::exception& e){ throw; } }
void App::scanForPK3() { logstream() << "Scanning for pk3s...\n"; #ifdef WIN32 _finddatai64_t fdata; base::String str(m_WorkingPath); str+="/*.pk3"; intptr_t handle=_findfirsti64(str.cstr(),&fdata); if (handle!=-1) { do { logstream() << "Found " << fdata.name << "\n"; PHYSFS_addToSearchPath(fdata.name,0); } while (_findnexti64(handle,&fdata)==0); _findclose(handle); } #else // POSIX #endif }
void FeaturesTable::TraverseDirectory(const std::string& path, std::string& pattern, bool subdirectories, std::vector<std::string>& fileNames) { struct _finddatai64_t data; std::string fname = path + "\\" + pattern; // start the finder -- on error _findfirsti64() will return -1, otherwise if no // error it returns a handle greater than -1. intptr_t h = _findfirsti64(fname.c_str(),&data); if(h >= 0) { do { if( (data.attrib & _A_SUBDIR) ) { if( subdirectories && strcmp(data.name,".") != 0 && strcmp(data.name,"..") != 0) { fname = path + "\\" + data.name; TraverseDirectory(fname,pattern,true, fileNames); } } else { fileNames.push_back(path + "\\" + data.name); } } while( _findnexti64(h,&data) == 0); _findclose(h); } }
/** * Move all files from temp to destination directory if at end of group */ void move_files(struct group_list_t *group) { char temppath[MAXPATHNAME], destpath[MAXPATHNAME]; char *filelist[10000]; // TODO: no magic number int len, filecount, i; if (!strcmp(tempdir, "") || (group->file_id != 0)) { return; } if (move_individual) { len = snprintf(temppath, sizeof(temppath), "%s%c_group_%08X", tempdir, PATH_SEP, group->group_id); if ((len >= sizeof(temppath)) || (len == -1)) { glog0(group, "Max pathname length exceeded: %s%c_group_%08X", tempdir, PATH_SEP, group->group_id); } else { move_files_individual(group, temppath, destdir[0]); } return; } { #ifdef WINDOWS intptr_t ffhandle; struct _finddatai64_t finfo; char dirglob[MAXPATHNAME]; snprintf(dirglob, sizeof(dirglob), "%s%c_group_%08X%c*", tempdir, PATH_SEP, group->group_id, PATH_SEP); if ((ffhandle = _findfirsti64(dirglob, &finfo)) == -1) { gsyserror(group, "Failed to open directory %s", dirglob); return; } filecount = 0; do { len = snprintf(temppath, sizeof(temppath), "%s%c_group_%08X%c%s", tempdir, PATH_SEP, group->group_id, PATH_SEP, finfo.name); if ((len >= sizeof(temppath)) || (len == -1)) { glog0(group,"Max pathname length exceeded: %s%c_group_%08X%c%s", tempdir, PATH_SEP, group->group_id, PATH_SEP, finfo.name); continue; } len = snprintf(destpath, sizeof(destpath), "%s%c%s", destdir[0], PATH_SEP, finfo.name); if ((len >= sizeof(destpath)) || (len == -1)) { glog0(group, "Max pathname length exceeded: %s%c%s", destdir[0], PATH_SEP, finfo.name); continue; } // do the move if (strcmp(finfo.name, ".") && strcmp(finfo.name, "..")) { clear_path(destpath, group); if (!MoveFile(temppath, destpath)) { char errbuf[300]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, errbuf, sizeof(errbuf), NULL); glog0(group, "error (%d): %s", GetLastError(), errbuf); } filelist[filecount] = strdup(destpath); if (filelist[filecount] == NULL) { gsyserror(group, "strdup failed!"); exit(ERR_ALLOC); } filecount++; } } while (_findnexti64(ffhandle, &finfo) == 0); _findclose(ffhandle); #else DIR *dir; struct dirent *de; char dirname[MAXPATHNAME]; snprintf(dirname, sizeof(dirname), "%s%c_group_%08X", tempdir, PATH_SEP, group->group_id); if ((dir = opendir(dirname)) == NULL) { gsyserror(group, "Failed to open directory %s", dirname); return; } filecount = 0; // errno needs to be set to 0 before calling readdir, otherwise // we'll report a false error when we exhaust the directory while ((errno = 0, de = readdir(dir)) != NULL) { len = snprintf(temppath, sizeof(temppath), "%s%c%s", dirname, PATH_SEP, de->d_name); if ((len >= sizeof(temppath)) || (len == -1)) { glog0(group, "Max pathname length exceeded: %s%c%s", dirname, PATH_SEP, de->d_name); continue; } len = snprintf(destpath, sizeof(destpath), "%s%c%s", destdir[0], PATH_SEP, de->d_name); if ((len >= sizeof(destpath)) || (len == -1)) { glog0(group, "Max pathname length exceeded: %s%c%s", destdir[0], PATH_SEP, de->d_name); continue; } if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) { clear_path(destpath, group); if (rename(temppath, destpath) == -1) { gsyserror(group, "Couldn't move file"); } filelist[filecount] = strdup(destpath); if (filelist[filecount] == NULL) { gsyserror(group, "strdup failed!"); exit(ERR_ALLOC); } filecount++; } } if (errno && (errno != ENOENT)) { gsyserror(group, "Failed to read directory %s", dirname); } closedir(dir); #endif } run_postreceive_multi(group, filelist, filecount); for (i = 0; i < filecount; i++) { free(filelist[i]); } snprintf(temppath, sizeof(temppath), "%s%c_group_%08X", tempdir, PATH_SEP, group->group_id); if (rmdir(temppath) == -1) { gsyserror(group, "Failed remove temp directory %s", temppath); } }
/** * Removes a full path from disk */ void clear_path(const char *path, int listidx) { stat_struct statbuf; char filename[MAXPATHNAME]; int len; if (lstat_func(path, &statbuf) == -1) { if (errno != ENOENT) { syserror(group_list[listidx].group_id, group_list[listidx].file_id, "Error getting file status for %s", path); } return; } if (!S_ISDIR(statbuf.st_mode)) { unlink(path); } else { #ifdef WINDOWS intptr_t ffhandle; struct _finddatai64_t finfo; char dirglob[MAXPATHNAME]; snprintf(dirglob, sizeof(dirglob), "%s%c*", path, PATH_SEP, group_list[listidx].group_id, PATH_SEP); if ((ffhandle = _findfirsti64(dirglob, &finfo)) == -1) { syserror(group_list[listidx].group_id, group_list[listidx].file_id, "Failed to open directory %s", path); return; } do { len = snprintf(filename, sizeof(filename), "%s%c%s", path, PATH_SEP, finfo.name); if ((len >= sizeof(filename)) || (len == -1)) { log0(group_list[listidx].group_id, group_list[listidx].file_id, "Max pathname length exceeded: %s%c%s", filename, PATH_SEP, finfo.name); continue; } if (strcmp(finfo.name, ".") && strcmp(finfo.name, "..")) { clear_path(filename, listidx); } } while (_findnexti64(ffhandle, &finfo) == 0); _findclose(ffhandle); #else DIR *dir; struct dirent *de; if ((dir = opendir(path)) == NULL) { syserror(group_list[listidx].group_id, group_list[listidx].file_id, "Failed to open directory %s", path); return; } // errno needs to be set to 0 before calling readdir, otherwise // we'll report a false error when we exhaust the directory while ((errno = 0, de = readdir(dir)) != NULL) { len = snprintf(filename, sizeof(filename), "%s%c%s", path, PATH_SEP, de->d_name); if ((len >= sizeof(filename)) || (len == -1)) { log0(group_list[listidx].group_id, group_list[listidx].file_id, "Max pathname length exceeded: %s%c%s", path, PATH_SEP, de->d_name); continue; } if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) { clear_path(filename, listidx); } } if (errno && (errno != ENOENT)) { syserror(group_list[listidx].group_id, group_list[listidx].file_id, "Failed to read directory %s", path); } closedir(dir); #endif if (rmdir(path) == -1) { syserror(group_list[listidx].group_id, group_list[listidx].file_id, "Failed remove directory %s", path); } } }
/** * Performs the send for a particular file/directory. If a directory is * specified, get the list of files and call recursively for each. * Returns 0 if a file was sent and none received it, 1 otherwise */ int send_file(const char *basedir, const char *filename, const char *n_destfname, uint32_t group_id) { static uint16_t file_id = 1; struct finfo_t finfo; stat_struct statbuf; char path[MAXPATHNAME], destpath[MAXPATHNAME]; int len, rval, fd, emptydir; log(0, 0, "----- %s -----", filename); len = snprintf(path, sizeof(path), "%s%c%s", basedir, PATH_SEP, filename); if ((len >= sizeof(path)) || (len == -1)) { log(0, 0, "Max pathname length exceeded: %s%c%s", basedir, PATH_SEP, filename); return 1; } if (follow_links) { rval = stat_func(path, &statbuf); } else { rval = lstat_func(path, &statbuf); } if (rval == -1) { syserror(0, 0, "Error getting file status for %s", filename); return 1; } if (file_excluded(filename)) { log(0, 0, "Skipping %s", filename); return 1; } rval = 1; if (S_ISREG(statbuf.st_mode)) { if ((fd = open(path, OPENREAD, 0)) == -1) { syserror(0, 0, "Error reading file %s", filename); return 1; } close(fd); memset(&finfo, 0, sizeof(struct finfo_t)); finfo.ftype = FTYPE_REG; finfo.basedir = basedir; finfo.filename = filename; finfo.destfname = n_destfname; finfo.group_id = group_id; finfo.file_id = file_id++; if (file_id == 0) { file_id = 1; } finfo.size = statbuf.st_size; finfo.blocks = (int32_t)((finfo.size / blocksize) + (finfo.size % blocksize ? 1 :0)); finfo.sections = (finfo.blocks / (blocksize * 8)) + (finfo.blocks % (blocksize * 8) ? 1 : 0); finfo.naklist = calloc(finfo.blocks, 1); finfo.deststate = calloc(destcount ? destcount : MAXDEST, sizeof(struct deststate_t)); if ((finfo.naklist == NULL) || (finfo.deststate == NULL)) { syserror(0, 0, "calloc failed!"); exit(1); } finfo.partial = 1; rval = announce_phase(&finfo); if (rval) { rval = transfer_phase(&finfo); } free(finfo.deststate); free(finfo.naklist); #ifndef WINDOWS } else if (S_ISLNK(statbuf.st_mode)) { char linkname[MAXPATHNAME]; memset(linkname, 0, sizeof(linkname)); if (readlink(path, linkname, sizeof(linkname)-1) == -1) { syserror(0, 0, "Failed to read symbolic link %s", path); return 1; } // Both the file name and the link have to fit into a fileinfo_h.name if (strlen(linkname) + strlen(filename) + 2 > MAXPATHNAME) { log(0, 0, "Combined file name %s and link %s too long", filename, linkname); return 1; } memset(&finfo, 0, sizeof(struct finfo_t)); finfo.ftype = FTYPE_LINK; finfo.basedir = basedir; finfo.filename = filename; finfo.destfname = n_destfname; finfo.linkname = linkname; finfo.group_id = group_id; finfo.file_id = file_id++; if (file_id == 0) { file_id = 1; } finfo.deststate = calloc(destcount ? destcount : MAXDEST, sizeof(struct deststate_t)); if (finfo.deststate == NULL) { syserror(0, 0, "calloc failed!"); exit(1); } finfo.partial = 1; rval = announce_phase(&finfo); if (rval) { rval = transfer_phase(&finfo); } #endif } else if (S_ISDIR(statbuf.st_mode)) { // read directory and do recursive send #ifdef WINDOWS intptr_t ffhandle; struct _finddatai64_t ffinfo; char dirglob[MAXPATHNAME]; snprintf(dirglob, sizeof(dirglob), "%s%c%s%c*", basedir, PATH_SEP, filename, PATH_SEP); if ((ffhandle = _findfirsti64(dirglob, &ffinfo)) == -1) { syserror(0, 0, "Failed to open directory %s%c%s", basedir, PATH_SEP, filename); return 1; } emptydir = 1; do { len = snprintf(path, sizeof(path), "%s/%s", filename, ffinfo.name); if ((len >= sizeof(path)) || (len == -1)) { log(0, 0, "Max pathname length exceeded: %s/%s", filename, ffinfo.name); continue; } len = snprintf(destpath, sizeof(destpath), "%s/%s", n_destfname, ffinfo.name); if ((len >= sizeof(destpath)) || (len == -1)) { log(0, 0, "Max pathname length exceeded: %s/%s", n_destfname, ffinfo.name); continue; } if (strcmp(ffinfo.name, ".") && strcmp(ffinfo.name, "..")) { emptydir = 0; if (!send_file(basedir, path, destpath, group_id)) { rval = 0; break; } } } while (_findnexti64(ffhandle, &ffinfo) == 0); _findclose(ffhandle); #else DIR *dir; struct dirent *de; char dirname[MAXPATHNAME]; snprintf(dirname, sizeof(dirname), "%s%c%s", basedir,PATH_SEP,filename); if ((dir = opendir(dirname)) == NULL) { syserror(0, 0, "Failed to open directory %s", dirname); return 1; } // errno needs to be set to 0 before calling readdir, otherwise // we'll report a false error when we exhaust the directory emptydir = 1; while ((errno = 0, de = readdir(dir)) != NULL) { len = snprintf(path, sizeof(path), "%s/%s", filename, de->d_name); if ((len >= sizeof(path)) || (len == -1)) { log(0, 0, "Max pathname length exceeded: %s/%s", filename, de->d_name); continue; } len = snprintf(destpath, sizeof(destpath), "%s/%s", n_destfname, de->d_name); if ((len >= sizeof(destpath)) || (len == -1)) { log(0, 0, "Max pathname length exceeded: %s/%s", n_destfname, de->d_name); continue; } if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) { emptydir = 0; if (!send_file(basedir, path, destpath, group_id)) { rval = 0; break; } } } if (errno && (errno != ENOENT)) { syserror(0, 0, "Failed to read directory %s", filename); } closedir(dir); #endif if (emptydir) { memset(&finfo, 0, sizeof(struct finfo_t)); finfo.ftype = FTYPE_DIR; finfo.basedir = basedir; finfo.filename = filename; finfo.destfname = n_destfname; finfo.group_id = group_id; finfo.file_id = file_id++; if (file_id == 0) { file_id = 1; } finfo.deststate = calloc(destcount ? destcount : MAXDEST, sizeof(struct deststate_t)); if (finfo.deststate == NULL) { syserror(0, 0, "calloc failed!"); exit(1); } finfo.partial = 1; rval = announce_phase(&finfo); if (rval) { rval = transfer_phase(&finfo); } } } else { log(0, 0, "Skipping special file %s", filename); } return rval; }