Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete link to file without clearing readonly bit

I have a set of files with multiple links to them.

The files are owned by TFS source control but other links to them are made to them. How do I delete the additional links without clearing the readonly bit.

It's safe to assume:

  • The files have more than one link to them
  • You are not deleting the name owned by TFS
  • There are no potential race conditions
  • You have ACL full control for the files
  • The machine will not lose power, nor will your program be killed unless it takes way too long.

It's not safe to assume:

  • The readonly bit is set (don't set it if its not)
  • You can leave the readonly bit clear if you encounter an error and it was initially set

Do not migrate to superuser -- if migrated there the answer is impossible because no standard tool can do this.

On a hypothetical *nix system in which one needs write permission on a file to delete it, there is a solution involving fchmod(). However the system that exhibiting this behavior is a Windows system.

like image 438
Joshua Avatar asked Dec 29 '22 13:12

Joshua


2 Answers

Have you tried enabling SeBackupPrivilege and SeRestorePrivilege, which allow admins to relax many of the security checks?

You might find this newsgroup thread helpful.

EDIT: To do it without privileges, and without creating a race condition, you'll need transactional NTFS support present in Vista and above. BTW, you can set attributes using a handle, pass FILE_BASIC_INFO to SetFileInformationByHandle, which can be transacted, see the notes. Or you can use FindFirstFileName to find another hard link to the same file which isn't being deleted, with which to set read-only.

  • CreateTransaction
  • GetFileAttributesTransacted
  • SetFileAttributesTransacted
  • CreateFileTransacted or FindFirstFileNameTransactedW
  • DeleteFileTransacted
  • SetFileInformationByHandle or SetFileAttributesTransacted again
  • CommitTransaction
like image 65
Ben Voigt Avatar answered Jan 12 '23 01:01

Ben Voigt


Thanks to Ben Voigt:

#include <windows.h>

int main(int argc, char **argv)
{
    while (*++argv) {
        HANDLE h;
        DWORD attrs;

        attrs = GetFileAttributes(*argv);
        SetFileAttributes(*argv, attrs & ~FILE_ATTRIBUTE_READONLY);
        h = CreateFile(*argv, GENERIC_READ|GENERIC_WRITE, 7, NULL, OPEN_EXISTING,
                    FILE_FLAG_DELETE_ON_CLOSE, NULL);
        SetFileAttributes(*argv, attrs);
        if (h != INVALID_HANDLE_VALUE) {
            CloseHandle(h);
        }
    }
}
like image 34
Joshua Avatar answered Jan 12 '23 01:01

Joshua