Accessing files across the windows network with near MAX_PATH length - c++

I'm using C++ and accessing a UNC path across the network. This path is slightly greater than MAX_PATH. So I cannot obtain a file handle.
But if I run the program on the computer in question, the path is not greater than MAX_PATH. So I can get a file handle. If I rename the file to have less characters (minus length of computer name) I can access the file.
Can this file be accessed across the network even know the computer name in the UNC path puts it over the MAX_PATH limit?

I recall that there is some feature like using \\?\ at the start of the path to get around the MAX_PATH limit. Here is a reference on MSDN:
http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
For remote machines, you would use a path name such as: \\?\unc\server\share\path\file. The \\?\unc\ is the special prefix and is not used as part of the actual filename.

You might be able to get a handle to the file if you try opening the file after converting the file name to a short (8.3) file name. Failing that can you map the dir the file is in as a drive and access the file that way?

Related

Overcome MAX_PATH filename length

I have read a lot of documentation on this subject, but I can't seem to figure it out.
The cause is that I have to process file paths which may be longer than the MAX_PATH parameter, causing a lot of issues
I have already replaced all my ANSI-functions like GetFileAttributesA with the UNICODE equivalent (GetFileAttributesW) in order to support the extended file path length with the prefix: \\?\.
However, I also need to check whether the file path for instance is a symbolic link and I need to know the filesize, last modified date, etc.
In order to do so, I use the stat function, as shown below:
if (fstat(LongFilePath, &file_info) == 0) //THIS FAILS WITH THE ENAMETOOLONG FOR LONG FILEPATHS
So, here again, the problem is in the ENAMETOOLONG error, due to a too long filename (exceeding MAX_PATH).
So, I found out I could use fstat to access the file by its descriptor. However, to obtain the descriptor, I need to use fopen, which also has the ENAMETOOLONG limitation.
So, my question is. How can I get the file information I need (symlink, filesize, last modified, .... as the stat function offers) for file paths exceeding MAX_PATH

Are file names allowed to have '/' in them?

I am confused by a piece of Python code:
with open('/dev/null', 'w+') as null:
It may be because I do not have knowledge of other Operating Systems, but I thought file names are forbidden to have '/' character. If so, I do not understand how this is a valid command.
Now I do understand that when using the open function in Python, if the file exist in a directory other than the current working directory, one has to prepend the path to the file name argument. However, this does not seem to be the case here because the file name argument for the open function is simply '/dev/null/'. Is 'null' the file name.
Is this related to this:
https://en.wikipedia.org/wiki/Null_device
"in some operating systems, the null device is a device file that discards all data written to it but reports that the write operation succeeded. This device is called /dev/null on Unix and Unix-like systems"
On Unix systems, file name cannot contain forward slash as it's used as directory separator. A file can't have a name of exactly one or two dots as they're used for "current directory" and "parent directory", too. A path starting with a forward slash is an absolute path, going all the way down the directory tree from the root path.
In that code, it opens /dev/null, a special character device that discards everything written to it and reports write success. It's possible that in some cases one wants to discard the output from a specific function, like subprocess.run. In this case, opening a handle to the null device is useful.

Can't open a file in C/C++ using eclipse cdt

I have a medium size program I'm developing using eclipse, I can't show the content because it would be too large. At some point I have some lines of fopen, I'm basically trying to create a new file and printing inside such file a content that has been derived from some processing.
So my line is something like a classic
FILE* f = fopen(filename,"w");
where filename is a char array large enough. However the FILE* returned is 0, and when I check the errno it is number 2, which means that the file doesn't exists.
However that's the point, I was trying to create a new file.
Is there something you could suggest that can I further check?
It's worth to note I'm running this stuff on unix, not windows.
Is the value of filename an absolute path or a relative one? If it's the latter, then probably the process you run hasn't the cwd (current working directory) you think it has.
Try using an absolute path, if that works then
use the chdir system call at the begin of main to set the cwd
Your filename might be incorrectly built, or you have no access to the path, or parts of the path don't exist.
Try a simple and clearly legal path first, like C:\\Temp\\x.x or something similar. if this works, it is not your code, but the filename.

Recovering Files on Windows and C

Well this time I'm trying to write a program in C which recover deleted files from a disk, it could be an external disk, I have an idea than i had used before on linux, it is to open the disk as a kind of file and scaning the Headers and file footers of everything within the disk, the point is I'm not sure if there's allow on windows to open a disk as an File, basiclly I have the logic how to develope this program, but I'm not sure how to implement it on windows, anybody can give me a hand with this?.
The code I used on linux to open a disk as a file was:
Edit: That was a sample of what I was using guys, it's just to give you an idea of what I was doing, the correct syntax I used was the next:
direccion = ui->linea->text().toLatin1().constData();
f = fopen(direccion,"rb");
I used QT creator on linux, and direccion variable was a TextField value which contained the file path of the disk through a button function that open a QFileDialog...
could I use it in windows as well?
Thank you before hand..
"The code I used on linux to open a disk as a file was:"
File *f = fopen("E:\", "rb");
I seriously doubt you ever got this code working on any linux system (or windows either).
You'll need to escape the backslash path delimiter, if it's presented in any string literal:
FILE* f = fopen("E:\\", "rb");
// ^
Also all that filesystem path style you are presenting to access a particular disk, is about accessing a windows file path/disk.
No linux file system has notion about drive characters, and the file path delimiter value used is '/', not '\\'.
To recover deleted files, you can't use fopen or fstream::open because the file was deleted. Check the return value from the function or test the stream state.
The way to recover deleted files is:
Get the Master File Table as raw data.
Search for the record containing a string similar to the deleted
filename.
Change the entry in the Master File Table to "undeleted".
Write the Master File Table back to the drive.
The above usually requires platform specific API, which is different on Linux and Windows platforms.

Efficiently List All Sub-Directories in a Directory

Please see edit with advice taken so far...
I am attempting to list all the directories(folders) in a given directory using WinAPI & C++.
Right now my algorithm is slow & inefficient:
- Use FindFirstFileEx() to open the folder I am searching
- I then look at every file in the directory(using FindNextFile()); if its a directory file then I store its absolute path in a vector, if its just a file I do nothing.
This seems extremely inefficient because I am looking at every file in the directory.
Is there a WinAPI function that I can use that will tell me all the sub-directories in a given directory?
Do you know of an algorithm I could use to efficiently locate & identify folders in a directory(folder)?
EDIT:
So after taking the advice I have searched using FindExSearchLimitToDirectories but for me it still prints out all the files(.txt, etc.) & not just folders. Am I doing something wrong?
WIN32_FIND_DATA dirData;
HANDLE dir = FindFirstFileEx( "c:/users/soribo/desktop\\*", FindExInfoStandard, &dirData,
FindExSearchLimitToDirectories, NULL, 0 );
while ( FindNextFile( dir, &dirData ) != 0 )
{
printf( "FileName: %s\n", dirData.cFileName );
}
In order to see a performance boost there must be support at the file system level. If this does not exist then the system must enumerate every single object in the directory.
In principle, you can use FindFirstFileEx specifying the FindExSearchLimitToDirectories flag. However, the documentation states (emphasis mine):
This is an advisory flag. If the file system supports directory filtering, the function searches for a file that matches the specified name and is also a directory. If the file system does not support directory filtering, this flag is silently ignored.
If directory filtering is desired, this flag can be used on all file systems, but because it is an advisory flag and only affects file systems that support it, the application must examine the file attribute data stored in the lpFindFileData parameter of the FindFirstFileEx function to determine whether the function has returned a handle to a directory.
However, from what I can tell, and information is sparse, FindExSearchLimitToDirectories flag is not widely supported on desktop file systems.
Your best bet is to use FindFirstFileEx with FindExSearchLimitToDirectories. You must still perform your own filtering in case you meet a file system that doesn't support directory filtering at file system level. If you get lucky and hit upon a file system that does support it then you will get the performance benefit.
If you're using FindFirstFileEx, then you should be able to specify the _FINDEX_SEARCH_OPS::FindExSearchLimitToDirectories option (to be used as the fSearchOp param in FindFirstFileEx) to limit the first search (and any subsequent FindNextFile()) calls to directories.