Engineer
Engineer

Reputation: 227

How to check if the file is still being copied in cpp using windows API?

In my current project, we had a requirement to check if the file is still copying.

We have already developed a library which will give us OS notification like file_added , file_removed , file_modified, file_renamed on a particular folder along with the corresponding file path.

The problem here is that, lets say if you add 1 GB file, it is giving multiple notification such as file_added , file_modified, file_modified as the file is being copied.

Now i decided to surpass these notifications by checking if the file is copying or not. Based on that i will ignore events.

I have written below function in c++ which tells if the file is being copied or not which takes file path as input. Details:- Basically it uses windows API "CreateFile" to get file handle. If we are not able acquire handle then it is determined as file is being copied.

Problem :- For some larger files like 2 GB with .rar & .exe format, this not working. Can you please advice me is this is right approach or not? If not appreciate other approaches.

bool isFileBeingCopied(const boost::filesystem::path &filePath)
{
     //Log(INFO, "Checking if the given file is being copied or not for the file [%s]",filePath.string().c_str());
     HANDLE hFile = ::CreateFile(filePath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
     DWORD dwLastError = GetLastError();

     if(hFile == NULL && hFile == INVALID_HANDLE_VALUE)
     {
          Log(INFO, "Gained invalid handle on the file - hence determining it, as being copied file [%s]",filePath.string().c_str());
          return true;
     }
     else
     {
          if(dwLastError == ERROR_SUCCESS )
          {
                CloseHandle(hFile);
                Log(INFO, "Able to gain the handle on the file - hence determining it, as copied file [%s]",filePath.string().c_str());
                return false;
          }
          else
          {
              Log(INFO, "Not able to gain the handle for the file - hence determining it, as being copied file [%s]",filePath.string().c_str());
              return true;
          }
     }               
}

Upvotes: 2

Views: 2386

Answers (3)

using boost filesystem libs, we can find out whether the file is getting copied or not. Basically boost::filesystem::fstream class opens the file for the I/O operations. When the file is currently getting copied, boost lib cannot open the file and is_open() method will return false. So, in this case, we can safely assume that file is currently getting copied. If the file is broken or damaged also, we end up being in this situation.

In all the other cases, is_open() returns true and we can consider as file copy is done(in this use case) Hope this code helps.

boost::filesystem::fstream fileStream(filePath, std::ios_base::in | std::ios_base::binary);

if(fileStream.is_open())
{
    //We could open the file, so file is good
    //So, file is not getting copied.
}
else
{
    //Wait, the file is currently getting copied. 
}

EDIT: Added more explanation

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 598309

Unless you are copying the file yourself,there is no way to determine the file's copy state externally. You will likely have to use a timer to detect when the file modified events stop being sent to you.

Upvotes: 1

Alexey Frunze
Alexey Frunze

Reputation: 62106

If the file has been previously open (and still is) with dwShareMode = 0, IOW, in an exclusive access mode, you won't be able to open it again until it closes, irrespective of whether the file is being copied (=written to) or not, and so your function's return value of true cannot be relied upon.

Note that if CreateFile() succeeds, you call CloseHandle() and return false. Immediately after this the file can get opened for writing by another process, and, again, the returned value of false cannot be relied upon because of the possibility of this race condition. If you want to prevent it, you must not close the handle until you no longer interested in having exclusive access to the file.

So, this is clearly not the right way to determine precisely whether a file is being copied (=written to) or not. And it appears as a meaningless thing to do.

It seems to me that you're trying to solve the wrong problem here. What's the real problem in whose context you have decided to check if a file is being copied (=written to) or not? If you tell us that, we might be able to help with that real problem.

Upvotes: 0

Related Questions