3

I'm writing a shell script that will run on Linux but can operate on files sitting on a mounted partition,

  1. that may or may not have an ext* file-system. It could eg be NTFS, FAT32, or any inode- or non-inode-based system;

  2. that could get further re-mounted on other boxes running non-Linux OSes like Windows or Mac.

Further, my script needs to be able to delete a file on this shared, arbitrarily formatted partition (even while the file's being read from or written to) by a remote process running on Linux, Windows, or Mac boxes

Questions:

  1. Is the ability to be able to delete a file in use a feature of,

    a. only the file-system?

    b. or, only the OS?

    c. or, a combo of both?

  2. (Extension of Q1) Does it matter if the processe doing I/O on the file and the one deleting the file are both local or remote?

Harry
  • 3,684
  • 6
  • 39
  • 48
  • anyway file will be not deleted in windows, until exist reference (open handles, section) on it. all remote io on file implemented actually with help of local io. so always local io exist if you access file from remote – RbMm May 08 '18 at 10:04
  • You mean, EVEN if an ext* file-system were mounted on a Windows host *somehow*, a program running on a remote Linux host won't be able to delete a file opened by a program on the Windows host? – Harry May 08 '18 at 12:07
  • 1
    of course no. how remote host can open some file on windows ? only if exist some local agent inside windows, which process request from remote hosts and open,read,write,delete data by remote request. but all operation anyway will be doing local – RbMm May 08 '18 at 12:18
  • also read this [*Normally a file marked for deletion is not actually deleted until all open handles for the file have been closed and the link count for the file is zero. When marking a file for deletion using FILE_DISPOSITION_POSIX_SEMANTICS, the link gets removed from the visible namespace as soon as the POSIX delete handle has been closed, but the file’s data streams remain accessible by other existing handles until the last handle has been closed.*](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/ns-ntddk-_file_disposition_information_ex) – RbMm May 08 '18 at 12:19
  • the `FILE_DISPOSITION_POSIX_SEMANTICS` supported only begin from WIN10_RS1 version. by using this flag in request `NtSetInformationFile` with `FileDispositionInformationEx` or it shell `SetFileInformationByHandle` with `FileDispositionInfoEx` we can make file "invisible" but actually it will be destroyed only after last handle has been closed – RbMm May 08 '18 at 12:22

2 Answers2

4

Does it matter if the processes doing I/O on the file and the one deleting the file are both local or remote?

interesting - how remote system can access file (open, read-write data, delete) on windows direct ? really this impossible. we need some agent (LANMan server), running in the local system, which will be by remote commands (send say by Network Redirector) do local operations on file. so from file system view - all operations always local.

Is the ability to be able to delete a file in use a feature of

this is implemented of course by file system driver, but this driver written for concrete OS and based on it rules. while file system data on disk is have common format (as result drive formatted(and written files) in one OS, can be read from another OS) - how file system driver process requests, open, read, write, delete files - this is OS specific. different for different OS. based on it rules. so data format on disk is common and only depend from file system. but how this data read/write/delete - already os specific.

in windows we have next rules for delete files:

Normally a file marked for deletion is not actually deleted until all open handles for the file have been closed and the link count for the file is zero. When marking a file for deletion using FILE_DISPOSITION_POSIX_SEMANTICS, the link gets removed from the visible namespace as soon as the POSIX delete handle has been closed, but the file’s data streams remain accessible by other existing handles until the last handle has been closed.

so in general file will be not deleted, until the last handle to it will be closed. file became not accessible after we try delete it - can not more open it (we get error A non close operation has been requested of a file object with a delete pending. if try do this, after file marked to delete). but if file was already opened - we can still work with it by this handle. also file can not be deleted if section exist on file - will be error An attempt has been made to remove a file or directory that cannot be deleted.

begin from win10 redstone1 build exist FILE_DISPOSITION_POSIX_SEMANTICS flag which let removed file name from the visible namespace when delete handle has been closed, but the file’s data streams remain accessible by other existing handles until the last handle has been closed

windows code test demo: (FILE_DISPOSITION_POSIX_SEMANTICS supported by ntfs begin only from _WIN32_WINNT_WIN10_RS1. FileDispositionInfoEx information class also supported begin from _WIN32_WINNT_WIN10_RS1 only. in previous build we simply got not implemented error)

void print_error(PCSTR name)
{
    PWSTR sz;
    NTSTATUS status = RtlGetLastNtStatus();
    if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_HMODULE, 
        GetModuleHandle(L"ntdll"), status, 0, (PWSTR)&sz, 0, 0))
    {
        DbgPrint("%s=%x\n%S\n", name, status, sz);
        LocalFree(sz);
    }
}

HANDLE OpenFile(PCWSTR lpFileName, DWORD dwDesiredAccess)
{
    HANDLE hFile = CreateFileW(lpFileName, dwDesiredAccess, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);

    if (hFile == INVALID_HANDLE_VALUE)
    {
        print_error("OpenFile");
        return 0;
    }

    return hFile;
}

void ReadTest(HANDLE hFile)
{
    if (hFile)
    {
        ULONG dwBytes;
        if (ReadFile(hFile, &dwBytes, sizeof(dwBytes), &dwBytes, 0))
        {
            DbgPrint("ReadFile=OK\n");
        }
        else
        {
            print_error("ReadFile");
        }
    }
}

void DeleteTest(PCWSTR lpFileName)
{
    HANDLE hFile1, hFile2, hFile3;

    if (hFile1 = OpenFile(lpFileName, DELETE))
    {
        hFile2 = OpenFile(lpFileName, FILE_GENERIC_READ);

        FILE_DISPOSITION_INFO_EX fdi = { FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS };
        if (!SetFileInformationByHandle(hFile1, FileDispositionInfoEx, &fdi, sizeof(fdi)))
        {
            print_error("SetFileInformationByHandle");
        }

        // file already not accessible here (open must fail) but visible
        if (hFile3 = OpenFile(lpFileName, FILE_GENERIC_READ))
        {
            CloseHandle(hFile3);
        }

        ReadTest(hFile2);

        // win10 rs1: file removed from the visible namespace here
        CloseHandle(hFile1);

        // are file still visible ?
        if (hFile3 = OpenFile(lpFileName, FILE_GENERIC_READ))
        {
            CloseHandle(hFile3);
        }

        // are possible create new file with this name &
        hFile3 = CreateFileW(lpFileName, DELETE, 
            FILE_SHARE_VALID_FLAGS, 0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0);
        if (hFile3 == INVALID_HANDLE_VALUE)
        {
            print_error("CreateFile");
        }
        else
        {
            CloseHandle(hFile3);
            DbgPrint("CreateFile OK\n");
        }

        ReadTest(hFile2);

        if (hFile2)
        {
            CloseHandle(hFile2);
        }
    }
}

and output

OpenFile=c0000056
A non close operation has been requested of a file object with a delete pending.

ReadFile=OK
OpenFile=c0000034
Object Name not found.

CreateFile OK
ReadFile=OK
RbMm
  • 31,280
  • 3
  • 35
  • 56
  • 3
    Please stress that because `FileDispositionInfoEx` (NT `FileDispositionInformationEx`) is new in Windows 10 release 1709 (`_WIN32_WINNT_WIN10_RS1`), this operation is not supported yet by many file systems and not even by Microsoft's own fastfat (FAT32) file-system driver in release 1709. Also, this can't get around the shared-access mode, and most applications do not open files with delete sharing. POSIX style unlinking in Windows will remain outside the norm for a very long time. – Eryk Sun May 08 '18 at 14:55
  • 1
    @eryksun - i note that this is begin from begin from win10 redstone1. (based on header `#if/#endif` about fastfat not check, but on ntfs `FILE_DISPOSITION_POSIX_SEMANTICS` really work. interesting about `FILE_DISPOSITION_ON_CLOSE` flag. i assume that combine it with `FILE_DISPOSITION_DELETE` must work like open file with `FILE_FLAG_DELETE_ON_CLOSE` - so call will be no visible effect until handle not closed. but i got `STATUS_NOT_SUPPORTED` here. or may be i some wrong understand – RbMm May 08 '18 at 15:08
  • 1
    I know you noted that this is new in Windows 10 1709, but a reader may not realize that this operation is dependent on support in the file-system driver, and, in particular, the OP indicated that FAT32 support is required, but as of 1709 fastfat fails this operation with `STATUS_INVALID_PARAMETER`. I'll check the on-close flag with NTFS. Presumably this should clear the delete-on-close flag in the File object's context control block (CCB), which gets transferred to the file system's file/stream control block (FCB/SCB) when the File is closed. Convenient; previously this required a 2nd handle. – Eryk Sun May 08 '18 at 15:17
  • 1
    Ok the on-close flag is supported by NTFS and works like I supposed. Use `FILE_DISPOSITION_ON_CLOSE` to clear the delete-on-close disposition of the File object. – Eryk Sun May 08 '18 at 15:31
  • 1
    @eryksun - yes. if open file with `FILE_FLAG_DELETE_ON_CLOSE` the `FILE_DISPOSITION_ON_CLOSE|FILE_DISPOSITION_DO_NOT_DELETE` remove `FILE_FLAG_DELETE_ON_CLOSE` open option from CCB. but not visa versa - not set this option with `FILE_DISPOSITION_DELETE` how i initial assume. and redstone 1 - this is 1607 if i not mistake but not 1709 – RbMm May 08 '18 at 15:34
  • Yes, in the headers it's defined for `_WIN32_WINNT_WIN10_RS1`. I was quoting the release version from the [`FILE_INFORMATION_CLASS`](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ne-wdm-_file_information_class) docs without thinking about it (i.e. "This value is available starting with Windows 10, version 1709"). My comments about the ntfs and fastfat drivers apply to release 1709, the version I checked. – Eryk Sun May 08 '18 at 15:41
  • As to setting the delete-on-close flag in the CCB, that wouldn't be useful. You can set this flag directly in the FCB/SCB. – Eryk Sun May 08 '18 at 15:44
  • Guys, after going thru your responses... Since the filesystem driver is highly OS- and even version-specific, can we finally conclude that the answer to my original question is **1c**? The reason I do **not** anymore think it's **1b** is: There could in principle be a weird filesystem (both disk format + its driver on an OS/version) that prevents an OS/version from deleting a file in use regardless of the OS's API/flags...by simply returning an error code (on the attempted delete). *Right?* – Harry May 09 '18 at 01:39
  • @Harry - here question - what you mean under filesystem - data structures [ntfs,fat,ext*,..] only [this is common for different os] - or also how files created/opened/read/write/delete etc - this is not part of specification and depend from concrete OS. or you mean under FS concrete driver (say ntfs.sys in windows) which implement both this component - data structures and how it accessed/modified. and consider this driver as part of os or separate fs ? anyway question - how delete file - not part of ntfs,fat,ext*,. specification but only driver or os depend. – RbMm May 09 '18 at 06:56
  • and in windows, for prevent access (delete) some files - used not fs-driver modification - but [mini]filters for this driver, which and do this task – RbMm May 09 '18 at 06:56
  • By *filesystem*, I mean data structure + driver. To briefly use another example: Non inode-like filesystems (such as ntfs, fat) may not be able to support hard-linking of files not merely because of missing support for this feature from their drivers but also due to inadequate structure of the filesystems themselves. As a programmer, I need to tell endusers of my program as to what all combos of OS+filesystems my program could run on if the same disk were mounted on different OSes on different boxes. So, obviously, I cannot disassociate driver from data structure when speaking of a filesystem. – Harry May 09 '18 at 07:15
0

it depends how do you define filesystem and OS. Generally, I understand under filesystem the way how the data storage is organized on a device. OS is then responsible for the I/O of data and files. Particularly, if your script wants to delete a file it calls some utility like rm and provides name of the file. This utility is a program which makes an appropriate system call. This system call is a part of operating system which is executed in the privileged mode. It realizes what and how to do (e.g. which drivers should be used to mark HDD blocks as free on a particular drive or maybe some remote procedure should be called or samba server involved etc.) So, to give an answer to your question 1, I would tend to the answer b.

rhaport
  • 540
  • 3
  • 11
  • My tentative understanding is, it's 1c. But not sure, 100%. – Harry May 08 '18 at 09:12
  • in your question you talk about ability to remove a file. At the end of the day the file will be removed by the local driver (local to the physical driver where it is located). Definitely a driver can do that. If you consider a driver as part of filesystem then the answer c. would be fine. I considered it as a part of OS. But back to the ability. If you consider the situation from the user perspective, it will – rhaport May 08 '18 at 09:42
  • ...the ability to remove a file the user (or script) will be considered from the user's local host. In this case, the feedback to the user will come from the operating system as the operating system. Local driver's function can always delete a file. Operating system needs to judge whether the file can be removed. It depends on the user access rights, availability if the remote host etc. – rhaport May 08 '18 at 10:01
  • *"At the end of the day the file will be removed"* - Not if some OS+fs combo locks the file and prevents its deletion while it's in use. My question has a development and testing aspect too: If the answer is 1a, I'll need to only test/research various file-systems. If the answer is 1b, then only the three OSes, and if it's 1c, then (yuck!) I must worry about various combos. User-rights and remote host-availability you can ignore for now. They aren't my concern at the moment. – Harry May 08 '18 at 12:05
  • there is a system call named unlink. This system call is responsible for file removing. Once it is called, the function do_unlinkat() which calls vfs_unlink(). So, the OS abstracts filesystem and calls iput function (in case of local file) which calls FS specific drop_inode function. In case of remote host the procedure is slightly different but similar. Important is that it happens in the system call context. Now, back to your question. As you see it is OS's responsibility to remove the file. Prerequisite is the correct configuration of your shared and local drives. – rhaport May 08 '18 at 13:25
  • The above comments refer to the script's perspective. How the file is really removed on the physical drive, it is responsibility of the driver. It might be quite complicated and involves some remote operations which should be supported by the remote host. – rhaport May 08 '18 at 13:28