C++ find file on LD_LIBRARY_PATH - c++

In C/C++ Is there an existing way to check to see if a particular file is on a particular path? I imagine syntax that might look like stat() but with additional parms for filename and path.
pathstat( struct stat stResult, const char* filename, const char* path );

using access() function with F_OK flag will check if your file exist. but before that you have to prepare the file path (from filename and path variables ) before pass the file path as input argument in the function access().
In this answer I assume that you use linux as platform
void pathstat( struct stat stResult, const char* filename, const char* path )
char *file;
int path_len;
if (!filename) {
// set error in the stResult
return;
}
path_len = path ? strlen(path) : 0;
file = malloc((strlen(filename) + path_len + 2) * sizeof(char));
// PREPARE THE FILE PATH
if (path && path[0] && path[path_len-1]=='/')
sprintf(file,"%s%s",path,filename);
else if (path && path[0])
sprintf(file,"%s/%s",path,filename);
else
file = strcpy(file,filename);
//NOW CHECK IF THE FILE PATH EXIST WITH ACCESS
if (access(file, F_OK) != -1) {
//file exist
} else {
// file does not exxit
}
free(file);
}

Related

How to open file with fopen() in UWP c++?

How can I open a file in UWP application?
My application will have additional files (e.g. Text file)
I want my program to be able to access this file. So how can I do it?
1.) Make sure that the file that you are trying to open is placed in Application local folder(Folder name "LocalState")
Use the below code to find the local folder path.
using namespace Windows::Storage;
using namespace Streams;
textBlock1->Text = ApplicationData::Current->LocalFolder->Path;
This will display local folder path in text block name textBlock1.
2.) To open the file name "Sample.txt"
using namespace Windows::Storage;
using namespace Streams;
String^ localfolder = ApplicationData::Current->LocalFolder->Path;
std::wstring basePath(localfolder->Data());
std::wstring fileName(L"\\Sample.txt");
basePath = basePath + fileName;
const wchar_t* fullpath = basePath.c_str();
size_t size = wcslen(fullpath) * 2 + 2;
char * StartPoint = new char[size];
size_t c_size;
wcstombs_s(&c_size, StartPoint, size, fullpath, size);
FILE *fp_testFile = NULL;
errno_t err;
err = fopen_s(&fp_testFile, StartPoint, "rb");
if (err == 0)
{
OutputDebugStringW(L"opened");
}
else
{
OutputDebugStringW(L"open failed");
}
The string conversion part is really confusing for me.
I also don't know how not to manually place the file in the local folder.
I tried added the file under Solution explorer -> Assets. But the file is not included to the local folder after deployed

FindNextFile Faild with Space Character

I wrote a simple code to do some operation on every file in every folder (subfolders).
It's perfectly works until the path comes with 'SPACE
' character program crashs and INVALID_HANDLE_VALUE has been called. This is function:
int dirListFiles(char* startDir)
{
HANDLE hFind;
WIN32_FIND_DATAA wfd;
char path[MAX_PATH];
sprintf(path, "%s\\*", startDir);
std::string fileName;
std::string s_path = startDir;
std::string fullPath;
fprintf(stdout, "In Directory \"%s\"\n\n", startDir);
if ((hFind = FindFirstFileA(path, &wfd)) == INVALID_HANDLE_VALUE)
{
printf("FindFirstFIle failed on path = \"%s\"\n", path);
abort();
}
BOOL cont = TRUE;
while (cont == TRUE)
{
if ((strncmp(".", wfd.cFileName, 1) != 0) && (strncmp("..", wfd.cFileName, 2) != 0))
{
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
sprintf(path, "%s\\%s", startDir, wfd.cFileName);
dirListFiles(path);
}
else
{
fileName = wfd.cFileName;
fullPath = s_path + "\\" + fileName;
std::string fileExt = PathFindExtension(fullPath.c_str());
if (fileExt == ".cpp")
{
... Some operation on file
}
}
}
cont = FindNextFile(hFind, &wfd);
}
FindClose(hFind);
For example, If FindNextFile wants to Open Program Files (x86) which has space between file name cause error and program exit. What Can I do for supporting spaces? What Is Problem?
Space is legal character in directory and file names.
First I propose to modify slightly your code:
if ((hFind = FindFirstFileA(path, &wfd)) == INVALID_HANDLE_VALUE)
{
printf("FindFirstFIle failed on path = \"%s\". Error %d\n", path, GetLastError());
return 0; // I think you shouldn't abort on error, just skip this dir.
}
Now check error codes reported by your program.
For some paths I have got error #5 (access denied). Examples:
c:\Program Files (x86)\Google\CrashReports\*
c:\ProgramData\Microsoft\Windows Defender\Clean Store\*
c:\Windows\System32\config\*
Got two cases with code #123 (Invalid name) for path names unmanageable by FindFirstFileA. To correct this behavior it would be better to use wide version of function FindFirstFileW. See both answers for c++ folder only search. For new Windows applications you should use wide version of API, converting with MultiByteToWideChar and WideCharToMultiByte if needed.
You have also logic error. Code skips all directories and files starting with dot.

c++ - fopen() internally changes my filename?

I use fopen() in my c++ program and I tried to open a .aff file.
I want to parse a file named car_wheel.aff and after if(ifp=fopen(path,"r")) has executed, it seems the fopen() function changes my path variable???
I add some detail to my question to the comment.
code (since variable path is constructed by my code, I put the whole piece of code here, which may seem a bit redundant.)
char* dir = "../kitchen/";
char filename[100];
char* path;
FILE *ifp;
int detail_level;
if(fscanf(fp,"%d %s",&detail_level,filename)!=2)
{
printf("Error: could not parse include.\n");
exit(0);
}
path = (char*)malloc(strlen(dir)+strlen(filename));
strcpy(path, dir);
strcat(path, filename); // path is "../kitchen/car_wheel.aff"
if(detail_level<=gDetailLevel)
{
if(ifp=fopen(path,"r"))
{
viParseFile(ifp);
fclose(ifp);
}
else
{
// jumped here and path became "../kitchen/car_wheel.aff1\002"
if (ifp == NULL) {
perror(path);
exit(EXIT_FAILURE);
}
printf("Error: could not open include file: <%s>.\n",filename);
exit(1);
}
}
I debugged the code in my ide, and it gave the filename char array is
and there is no '1\002' behind my filename variable. What happened??
The problem is here:
path = (char*)malloc(strlen(dir)+strlen(filename));
You don't allocate space for the terminating zero character. Change it to this:
path = (char*)malloc(strlen(dir)+strlen(filename)+1);

PathFileExists returns false when executing application through RemoteApp

My executable built in C++/WinAPI will check for a file placed in the same folder and I use PathFileExists for that. When I run it on a normal computer it finds the file but when I publish the executable on RemoteApp and I run it from Web Access the file is not found. What would I be missing?
// This is the file I want to find (located in the same directory as the EXE)
wstring myfile = L"myfile.conf";
BOOL abspath = FALSE;
// Trying to get the absolute path first
DWORD nBufferLength = MAX_PATH;
wchar_t szCurrentDirectory[MAX_PATH + 1];
if (GetCurrentDirectory(nBufferLength, szCurrentDirectory) == 0) {
szCurrentDirectory[MAX_PATH + 1] = '\0';
} else {
abspath = true;
}
if (abspath) {
// Create the absolute path to the file
myfile = L'\\' + myfile;
myfile = szCurrentDirectory + myfile ;
MessageBox(hWnd, ConvertToUNC(myfile).c_str(), L"Absolute Path", MB_ICONINFORMATION);
} else {
// Get the UNC path
myfile = ConvertToUNC(myfile);
MessageBox(hWnd, myfile.c_str(), L"UNC Path", MB_ICONINFORMATION);
}
// Try to find file
int retval = PathFileExists(myfile.c_str());
if (retval == 1) {
// Do something
} else {
// File not found
}
The ConvertToUNC function is copied from here.
What I see is that, although the executable lies somewhere else, the absolute path is considered to be C:\Windows. I really don't know what is causing this. The server is Windows 2012 R2 and, like I said, applications are run through RemoteApp Web Access. The returned UNC path is just the name of the file (no volume or folder)

Find all files in all directories in c++

I am trying to find all files in all directories, but I don't know how to handle subdirectories. In this code, the code looks trough all subdirs, but I don't know how to jump back. Does anyone know how to do this?
__declspec(dllexport) void GetFiles(char* filedir, char* path)
{
string s[1000];
string path2 = path;
UINT index = 0;
WIN32_FIND_DATA ffd;
TCHAR szDir[MAX_PATH];
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError=0;
StringCchCopy(szDir, MAX_PATH, filedir);
if (INVALID_HANDLE_VALUE == hFind)
return;
do
{
DWORD attributes = ffd.dwFileAttributes;
if (attributes & FILE_ATTRIBUTE_HIDDEN)
continue;
else if (attributes & FILE_ATTRIBUTE_DIRECTORY)
{
TCHAR dir2[MAX_PATH];
path2 = path;
path2 += ffd.cFileName;
path2 += "\\*";
StringCchCopy(dir2, MAX_PATH, path2.c_str());
SetCurrentDirectory(dir2);
}
else
{
s[index] = path;
s[index] += ffd.cFileName;
index++;
}
}
while (FindNextFile(hFind, &ffd) >= 0); // needs to jump back if zero
FindClose(hFind);
}
EDIT: functions had the same name which confused the compiler
I think the easiest way to do it is by doing a recursive function.
This would roughly look like something like this in "c" pseudo code
void GetFiles( char*** file_path_table, char* dir )
{
char **file_paths;
file_paths = getAllFiles( dir );
foreach( path in file_paths )
{
if ( is_directory( path ) )
{
GetFiles( file_path_table, path );
}
else
{
add_file_to_table( file_path_table, path );
}
}
}
Why not use the boost recursive_directory_iterator.
Note: untested (but should look something like this).
namespace bfs = boost::filesystem;
std::vector<std::string> filenames;
std::copy(bfs::recursive_directory_iterator("<path>"),
bfs::recursive_directory_iterator(),
std::back_inserter(filenames)
);
Instead of changing directory via SetCurrentDirectory() use a recursive call on GetFiles(). This would require that the caller pass in a reference to an array (or std::vector<std::string>) for the list of files to be stored in instead of using the local array s.
I'd have a look at the directory iterators of boost instead.
http://www.boost.org/doc/libs/1_51_0/libs/filesystem/doc/index.htm
There are examples covering what you are trying to do, and it will work for almost any OS you can think of.
Have a look at example 3. It shows how to loop over all contents of the directory. If you find a new directory you have not seen before, you just do the same on that. There are tests telling you if the file is regular, directory etc so give it a try.
Doing a bit of searching through old posts, I guess I've mentioned doing a breadth-first search a number of times, but never really posted code to show how to do it. I guess I might as well do that.
#include <windows.h>
#include <queue>
#include <string>
#include <iostream>
// I think MS's names for some things are obnoxious.
const HANDLE HNULL = INVALID_HANDLE_VALUE;
const int A_DIR = FILE_ATTRIBUTE_DIRECTORY;
// We'll process a file by printing its path/name
void process(std::string const &path, WIN32_FIND_DATA const &file) {
std::cout << path << file.cFileName << "\n";
}
void find_file(std::string const &folder_name, std::string const &fmask) {
HANDLE finder; // for FindFirstFile
WIN32_FIND_DATA file; // data about current file.
std::priority_queue<std::string, std::vector<std::string>,
std::greater<std::string> > dirs;
dirs.push(folder_name); // start with passed directory
do {
std::string path = dirs.top();// retrieve directory to search
dirs.pop();
if (path[path.size()-1] != '\\') // normalize the name.
path += "\\";
std::string mask = path + fmask; // create mask for searching
// traverse a directory. Search for sub-dirs separately, because we
// don't want a mask to apply to directory names. "*.cpp" should find
// "a\b.cpp", even though "a" doesn't match "*.cpp".
//
// First search for files:
if (HNULL==(finder=FindFirstFile(mask.c_str(), &file)))
continue;
do {
if (!(file.dwFileAttributes & A_DIR))
process(path, file);
} while (FindNextFile(finder, &file));
FindClose(finder);
// Then search for subdirectories:
if (HNULL==(finder=FindFirstFile((path + "*").c_str(), &file)))
continue;
do {
if ((file.dwFileAttributes & A_DIR) && (file.cFileName[0] != '.'))
dirs.push(path + file.cFileName);
} while (FindNextFile(finder, &file));
FindClose(finder);
} while (!dirs.empty());
}
int main(int argc, char **argv) {
if (argc > 2)
find_file(argv[1], argv[2]);
else
find_file("C:\\", "*");
return 0;
}