Opening a file in Mac OS X - c

I am trying to open a text file with C++ in Mac OS X but I always get a Bus error.
I do not care where to put the file. I just need to read it. Am I writing its address wrong? or that Bus Error has another reason?
FILE *dic;
dic = fopen("DICT","rb");
dic = fopen("./DICT","rb");
dic = fopen("~/DICT","rb");
dic = fopen("~//DICT","rb");

With a little bit of clarification I see the problem in your C code (not C++!) is that fopen() returns NULL. You can check what the problem really is by reporting the detailed error:
if( (dic = fopen("DICT", "rb") == NULL ) {
fprintf(stderr, "%s\n", perror("ERROR:"));
exit(1);
}
If fopen() fails to find the file on the user's desktop and you wish your code to work on multiple platforms then you might define a function to get the user's desktop directory for using with fopen(). Something like
char* user_desktop(char* buf, size_t len)
{
const char* const DESKTOP_DIR =
#ifdef PC
"C:\\Documents and Settings\\Pooya\\Desktop\\"
#elif defined(OSX)
"/Users/Pooya/Desktop/"
#elif defined(LINUX)
"/home/users/pooya/Desktop/"
// fail to compile if no OS specified ...
#endif
return strncpy(buf, DESKTOP_DIR, len);
}
You probably want to look into a more robust way of getting the path of the desktop for each operating system. Most operating systems have an API for this, so do your research. There are also more robust ways of splitting behaviour for various platforms, you can look into that or open a different question about that. I just wanted to express my idea, of having a function which will return you the appropriate desktop path no matter on which platform you compile your code.

This code is correct! Pay attention to the directory where the executable is located. For sure the directory of the execution is not the same as you are expecting (I suppose, the directory of the .c files, right?).
I believe you are executing the app from the IDE. This is commom in Xcode, it mounts the exec`s in another location than that where the project files are located, and this such location that is considered when you execute the program, whether you execute it from the IDE or not!
Simply move the file you want to read to the location of the application and it will work properly.

Related

How to compare two (absolute) paths (given as char* ) in C and check if they are the same?

Given two paths as char*, I can't determine if the two paths are pointing to the same file.
How to implement in C a platform-independent utility to check if paths are pointing to the same file or not.
Using strcmp will not work because on windows paths can contain \ or /
Using ist_ino will not help because it does not work on windows
char *fileName = du->getFileName();
char *oldFileName = m_duPtr->getFileName();
bool isSameFile = pathCompare(fileName, oldFileName) == 0;//(strcmp(fileName, oldFileName) == 0);
if (isSameFile){
stat(fileName, &pBuf);
stat(oldFileName, &pBuf2);
if (pBuf.st_ino == pBuf2.st_ino){
bRet = true;
}
}
You can't. Hard links also exist on Windows and the C standard library has no methods for operating on them.
Plausible solutions to the larger problem: link against cygwin1.dll and use the st_ino method. You omitted st_dev from your sample code and need to put it back.
While there is an actual way to accomplish this on Windows, it involves ntdll methods and I had to read Cygwin's code to find out how to do it.
The methods are NtGetFileInformationByHandle and NtFsGetVolumeInformationNyHandle. There are documented kernel32 calls that claim to do the same thing. See the cygwin source code for why they don't work right (buggy fs drivers).

Calling fopen on Windows core files returns NULL pointer

I am trying to open a couple different files via their absolute path (determined elsewhere, programmatically), so I can get their SHA1 hash*, some of which are core windows files. fopen() is returning NULL on some (but not all) files when I attempt to open them as follows (normally the filename is gotten via QueryFullProcessImageName but I hardcoded it just in case):
char * filename = "c:\\windows\\system32\\spoolsv.exe";
FILE * currFileRead = fopen(filename, "rb");
if (currFileRead == NULL)
{
printf("Failed to open %s, error %s\n", filename, strerror(errno) );
}
else
{
//hashing code
}
The reported error is 2: "No such file or directory", but obviously they're there. It also only fails for some processes, like spoolsv.exe or winlogon.exe, while svchost.exe and wininint.exe seem to open just fine.
My program has administrative privileges, and I can't figure why some processes would fail while others opened without trouble?
*I'm using a method from LibTomCrypt (http://libtom.org/?page=features) which is open source with a permissive license. The call to sha1_process takes in a hash_state (internal to the library), an unsigned char buffer, and the length of the buffer. I need to read the file with fopen to get the file into memory for hashing.
Because your program is a 32-bit process, when you try to open c:\windows\system32 you actually get c:\windows\syswow64 which does not contain all of the same files.
You can use IsWow64Process to determine whether you are running on a 64-bit system. If you are, you can replace system32 with sysnative in the path to open the actual file, unless you need to support Windows 2003 or Windows XP. Depending on your circumstances, you might need to cope with the possibility that the Windows folder is not c:\windows and/or the possibility that there are other folders named system32.
On the whole it would be more robust to have separate 32-bit and 64-bit versions of your application, or perhaps just the particular part of it that is exhibiting the problem. If you can't leave it up to the user to install the appropriate version, the installer could decide which to install, or you could always install both and have the 32-bit version automatically launch the 64-bit version when running on a 64-bit system.
Having administrative privileges is not always enough, because if the file you want to open is in use and the program that is using it has locked it, then you can't open and read that file.

program doesnt work if called from another folder

In Command Prompt, this works: whatever\folder> bezier.exe
but this doesn't: whatever> folder\bezier.exe
My bezier program loads some settings from a local file, so I believe the problem is that the program thinks its directory is whatever\ when it is actually whatever\folder\. I'm calling it from within a C program using CreateProcess(). If I am correct in guessing the problem, is there any way to ensure the program has the right directory for itself?
the main method of bezier.exe:
int main(int argc, char* argv[]) {
char buf[200];
FILE* f = fopen("out.txt","w");
GetCurrentDirectory(200,buf);
fprintf(f,buf);
fclose(f);
SDL_Surface* screen;
SDL_Event e;
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_FULLSCREEN|SDL_HWSURFACE);
if (screen == NULL)
exit(-1);
SDL_ShowCursor(SDL_DISABLE);
srand(time(NULL));
loadColors(COLOR_FILE);
fill(screen, backColor);
initialiseVars();
while (e.type != SDL_KEYDOWN)
{
//do stuff
}
SDL_Quit();
return 0;
}
Here's the crazy part. With "..> folder\bezier.exe" it doesn't write its path, but it does start a new window. That doesn't make any sense to me, because SDL_SetVideoMode is after writing the path.
You can use GetModuleHandle and GetModuleFileName to find out where your execuatble file is, then use that information to create a file specification for your local settings file.
GetModuleHandle with a NULL argument will give you the handle for the current executable. Then, passing that to GetModuleFileName will give you the fully qualified name of that executable. Just strip off the executable filename from the end and add your configuration file name.
However, that's been a bad idea for a long time now, since Windows provides per-application and per-user settings areas for this sort of stuff - you can generally get those locations with SHGetFolderLocation() and its brethren.
Use the first method only if this is for a personal project. If you plan to release your software to the wild, you should separate executable and configuration information as per Microsoft guidelines.
Regardless of that, it appears you now have the problem that you think the file is not being written to. You need to check that. When you open that file out.txt for write, it does so in the current directory. If you're running in the parent directory (with folder\bezier.exe), it will create it in the parent directory and looking for it in the folder directory is a waste of time.
If you are looking in the directory where you're running the program from, and it's still not being created, there are possible reasons for this. For a start, you should check (ie, capture and output) the return codes from all those f* functions, fopen, fprintf and fclose.

to make a self-contained exe that extracts files and other commands

I am making a filtering sniffer in C and winPCAP that starts on every boot. For this I want to make a self-contained exe file that extracts (no, not compression!) the exe and DLLs to a new folder and performs other commands (like modify startup settings) silently, without showing any window/terminal.
So
The single file contains an exe and DLLs.
When executed, it copies the files to a folder and does other commands
It does it silently, without any windows or terminals or user intervention
I stress on the silent part, so I cant choose some easy installers. Can you reccomend something that generates this executable?
For the curious: its a stealth packet logger program for my college project. The "stealth" part will be tried out only on xp2 virtual machines with IE6 (yeah, old stuff).
EDIT: answering the commenters: it is of a malware character. So I am running it in virtualbox, never on the loose. And I can compromise only an unpatched xp systems with IE6, without antivirus, that is from an OLD install disk. Thats the scope of the IE css use after free vulnerability, AFAIK never seen in the wild. So there is no unethical behavior involved.
You can easily embed resources either by linking them in, with the compiler, or by using a special program and instrumenting the windows API.
Something along the lines of :
char file_to_be_altered[] = "MyInstaller.exe"
HANDLE hUpdate = BeginUpdateResource( file_to_be_altered, FALSE );
UpdateResource( hUpdate, "MyResType", "MyResName1", 0, pData, data_len );
EndUpdateResource( hUpdate, FALSE );
Then when your executable runs, you enumerate your resources and select those that have the type "MyResType".
struct res_entry { BYTE* pData; unsigned int len; }
BOOL CALLBACK EnumNamesCB(
HMODULE hModule, // module handle
LPCTSTR lpType, // address of resource type
LPTSTR lpName, // address of resource name
LONG_PTR lParam) //
{
std::vector<res_entry>& lst = *(reinterpret_cast< std::vector<res_entry>* >( lParam ));
HRSRC hRes = FindResource( hModule, lpName, lpType );
if( hRes == 0 ) return TRUE;
unsigned int len = SizeofResource( hModule, hRes );
HGLOBAL hGlob = LoadResource( hModule, hRes );
if( hGlob == 0 ) return TRUE;
res_entry t;
t.pData = LockResource( hGlob );
t.len = len;
lst.push_back( t ); // this is safe, because the resources are never deallocated
return TRUE;
}
....
void enum_entries()
{
std::vector<res_entry> lst;
::EnumResourceNames( hFileToQuery, "MyResType", &EnumNamesCB, reinterpret_cast<LONG_PTR>(&lst) );
}
You can do whatever you want with this data, e.g. CreateFile ... and the write the data out to disc.
NB: This is how installers may do it on windows, and this was developed to extract files to the temp dir and install from there.
The trivial way to do it is to create a very large array inside your program, and store the data to be extracted inside that array. When executed the program takes the array and writes it out to a file or files as needed, then executes the file you want to run once the files are extracted. See, for example, C Question: How to store data inside the executable file.
Once the program is compiled you can replace the data in the EXE using a binary editor to copy your files in place without having to convert your files to a C array or some other data structure every time you change your payload.
In order to keep the size down the primary program typically decompresses the array and expects a compressed array. A lot of installers simply use zip as the decompressor takes care of multiple files in one array, and you don't have to fiddle with adding a directory array and reference array - it's all built in, and command line zip compressors are common and easy to use.
Whether the primary program opens a terminal depends on how you program it. I expect you'll need it to be a win32 program so windows doesn't open a DOS terminal, and you simply don't open any windows inside your program. That's a separate question, though, so consider asking it as a new question.
As David points out, this process is typically automated in the linker stage. Each linker is slightly different, but you can check out Embedding resources in .exe using GCC for an example using one of the more common compilers.
I assume you know what you are doing, but keep in mind that there are a lot of unpatched stock winxp sp2 systems out there - assuming that you won't hurt anyone because you don't believe such systems are online is a poor choice. Make certain that your program doesn't have the ability to leave the virtual machines. There are ways, for instance to connect their networks without allowing the machines access to the internet, or your computer's network. Keep in mind that the Morris worm was a pet project that wasn't intended or expected to go wild either.

How to check if a file is already open by another process in C?

I see that standard C has no way of telling if a file is already opened in another process. So the answer should contain several examples for each platform. I need that check for Visual C++ / Windows though.
Windows: Try to open the file in exclusive mode. If it works, no one else has opened the file and will not be able to open the file
HANDLE fh;
fh = CreateFile(filename, GENERIC_READ, 0 /* no sharing! exclusive */, NULL, OPEN_EXISTING, 0, NULL);
if ((fh != NULL) && (fh != INVALID_HANDLE_VALUE))
{
// the only open file to filename should be fh.
// do something
CloseHandle(fh);
}
MS says: dwShareMode
The sharing mode of an object, which can be read, write, both, delete, all of these, or none (refer to the following table).
If this parameter is zero and CreateFile succeeds, the object cannot be shared and cannot be opened again until the handle is closed.
You cannot request a sharing mode that conflicts with the access mode that is specified in an open request that has an open handle, because that would result in the following sharing violation: ERROR_SHARING_VIOLATION.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx
extension:
how to delete a (not readonly) file filesystem which no one has open for read/write?
access right FILE_READ_ATTRIBUTES, not DELETE. DELETE could cause problems on smb share (to MS Windows Servers) - CreateFile will leave with a still open FileHandle /Device/Mup:xxx filename - why ever and whatever this Mup is. Will not happen with access right FILE_READ_ATTRIBUTES
use FILE_FLAG_OPEN_REPARSE_POINT to delete filename. Else you will delete the target of a symbolic link - which is usually not what you want
HANDLE fh;
fh = CreateFile(filename, FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE /* no RW sharing! */, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_DELETE_ON_CLOSE, NULL);
if ((fh != NULL) && (fh != INVALID_HANDLE_VALUE))
{
DeleteFile(filename); /* looks stupid?
* but FILE_FLAG_DELETE_ON_CLOSE will not work on some smb shares (e.g. samba)!
* FILE_SHARE_DELETE should allow this DeleteFile() and so the problem could be solved by additional DeleteFile()
*/
CloseHandle(fh); /* a file, which no one has currently opened for RW is delete NOW */
}
what to do with an open file? If the file is open and you are allowed to do an unlink, you will be left a file where subsequent opens will lead to ACCESS_DENIED.
If you have a temporary folder, then it could be a good idea to rename(filename, tempdir/filename.delete) and delete tempdir/filename.delete.
There's no way tell, unless the other process explicitly forbids access to the file. In MSVC, you'd do so with _fsopen(), specifying _SH_DENYRD for the shflag argument. The notion of being interested whether a file is opened that isn't otherwise locked is deeply flawed on a multitasking operating system. It might be opened a microsecond after you'd have found it wasn't. That's also the reason that Windows doesn't have a IsFileLocked() function.
If you need synchronized access to files, you'll need to add this with a named mutex, use CreateMutex().
Getting the open_files information is DIFFICULT, it's like pulling teeth, and if you don't have an immediate need for it you shouldn't be asking for "several examples for each platform" just for the hell of it. Just my opinion, of course.
Linux and many Unix systems have a system utility called lsof which finds open file handles and stuff. The way it does so is by accessing /dev/kmem, which is a pseudo-file containing a copy of "live" kernel memory, i.e. the working storage of the operating system kernel. There are tables of open files in there, naturally, and the memory structure is open-source and documented, so it's just a matter of a lot of busywork for lsof to go in there, find the information and format it for the user.
Documentation for the deep innards of Windows, on the other hand, is practically nonexistent, and I'm not aware that the data structures are somehow exposed to the outside. I'm no Windows expert, but unless the Windows API explicitly offers this kind of information it may simply not be available.
Whatever is available is probably being used by Mark Russinovich's SysInternals utilities; the first one that comes to mind is FileMon. Looking at those may give you some clues. Update: I've just been informed that SysInternals Handles.exe is even closer to what you want.
If you manage to figure that out, good; otherwise you may be interested in catching file open/close operations as they happen: The Windows API offers a generous handful of so-called Hooks: http://msdn.microsoft.com/en-us/library/ms997537.aspx. Hooks allow you to request notification when certain things happen in the system. I believe there's one that will tell you when a program –systemwide– opens a file. So you can make your own list of files opened for the duration you're listening to your hooks. I don't know for sure but I suspect this may be what FileMon does.
The Windows API, including the hook functions, can be accessed from C. Systemwide hooks will require you to create a DLL to be loaded alongside your program.
Hope these hints help you get started.
For Windows, this code works also:
boolean isClosed(File f) { return f.renameTo(f); }
An opened file can not be renamed, and a rename to same name does not cause another error. So if the rename succeeds, not having really done something, you know the file is not open.
Any such check would be inherently racy. Another process could always open the file between the point where you did the check and the point where you accessed the file.
The answers so far should tell you that finding out the information you've asked for is tricky, non-portable, and often inherently unreliable. So, from my perspective, the real answer is don't do that. Try to find a way to think about your real problem so that this question doesn't arise.
this can't be that hard guys.
do this:
try{
File fileout = new File(path + ".xls");
FileOutPutStream out = new FileOutPutStream(fileout);
}
catch(FileNotFoundException e1){
// if a MS Windows process is already using the file, this exception will be thrown
}
catch(Exception e){
}
You can use something like this. It is not a proper solution. But it works,
bool IsFileDownloadComplete(const std::wstring& dir, const std::wstring& fileName)
{
std::wstring originalFileName = dir + fileName;
std::wstring tempFileName = dir + L"temp";
while(true)
{
int ret = rename(convertWstringToString(originalFileName).c_str(), convertWstringToString(tempFileName).c_str());
if(ret == 0)
break;
Sleep(10);
}
/** File is not open. Rename to original. */
int ret = rename(convertWstringToString(tempFileName).c_str(), convertWstringToString(originalFileName).c_str());
if(ret != 0)
throw std::exception("File rename failed");
return true;
}

Resources