Search code examples
cwindowswinapiwin32-process

DeleteFile() or unlink() calls succeed but doesn't remove file


I am facing this strange problem. To delete a file unlink() API is called in my code. This call removes the file and succeeds on non-windows platforms. On windows it succeeds (returns 0) but doesn't remove the file.

To experiment I added a loop to call same API repeatedly. In second iteration I got an Permission denied error, Error code =13. Though read/write attributes are set on file and program has full permission to access the file.

I then called DeleteFile() instead of unlink() API. To my surprise I see the same result,call succeeded i.e. returned 1 but file is not removed physically.

I checked through unlocker utility, no other program is accessing the file except the program which is trying to remove this file.

Does anyone has idea what else could be wrong ?

Edit1: Just to ensure file was not opened at the time of removing it. I saved the handle when file was created and tried to close before removing the file but I got error "'UNOPENED' (Errcode: 9 - Bad file descriptor)". Thus I conclude the file was not open at the time of removing it.

Edit2 As requested, here is the simplified version of code used to create and remove the file.

// Code to create the file
int create_file(const char* path)
{
  HANDLE osfh;                            /* OS handle of opened file */
  DWORD fileaccess;                       /* OS file access (requested) */
  DWORD fileshare;                        /* OS file sharing mode */
  DWORD filecreate;                       /* OS method of opening/creating */
  DWORD fileattrib;                       /* OS file attribute flags */
  SECURITY_ATTRIBUTES SecurityAttributes;


  SecurityAttributes.nLength= sizeof(SecurityAttributes);
  SecurityAttributes.lpSecurityDescriptor= NULL;
  SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);



 fileaccess= GENERIC_WRITE;
 fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
 filecreate= CREATE_NEW; 


 if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes, 
 filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
 {
   // error handling
 }

}

//Code to delete the file - 
int remove_file (const char* name)
{
  if ((err = unlink(name)) == -1)
  { //Error handling }
}

Edit3 As pointed by Joachim Pileborg and icabod, that DeleteFile() does not remove file if it is still open. As suggested by Remy Lebeau, to use process explorer. I found that one handle to file was indeed open when I closed that from process explorer file deleted like a charm :)

I had also mentioned in the Edit1 when I tried to close the file I got an error. It happened because the file descriptor I get from createfile() is not the actual handle returned by CreateFile() API instead a logical mapped handle due to underlying code complexities to support other non-windows platforms. Anyways, now I understood the root cause of problem but I was expecting if a file with open handle is passed to DeleteFile() API then it should fail in first attempt rather succeed and wait for open handles to close.


Solution

  • Assuming that you call your Createfile function, then later call your remove_file function... you still have a handle open to the file. The WinAPI function CreateFile, if it succeeds, keeps a handle open on the file. In your provided code, you don't close that handle.

    From the documentation on DeleteFile:

    The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed. Subsequent calls to CreateFile to open the file fail with ERROR_ACCESS_DENIED.

    My guess is that you still have a handle open, and when you close that handle the file will be deleted.

    However, your sample code is incomplete, so it is difficult to tell.