Function DeleteFile [src]

Prototype

pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFileError!void

Parameters

sub_path_w: []const u16options: DeleteFileOptions

Possible Errors

AccessDenied
DirNotEmpty
FileBusy

Also known as sharing violation.

FileNotFound
IsDir
NameTooLong
NetworkNotFound
NotDir
Unexpected

Source

pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFileError!void { const create_options_flags: ULONG = if (options.remove_dir) FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT else FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT; // would we ever want to delete the target instead? const path_len_bytes = @as(u16, @intCast(sub_path_w.len * 2)); var nt_name = UNICODE_STRING{ .Length = path_len_bytes, .MaximumLength = path_len_bytes, // The Windows API makes this mutable, but it will not mutate here. .Buffer = @constCast(sub_path_w.ptr), }; if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { // Windows does not recognize this, but it does work with empty string. nt_name.Length = 0; } if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) { // Can't remove the parent directory with an open handle. return error.FileBusy; } var attr = OBJECT_ATTRIBUTES{ .Length = @sizeOf(OBJECT_ATTRIBUTES), .RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else options.dir, .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. .ObjectName = &nt_name, .SecurityDescriptor = null, .SecurityQualityOfService = null, }; var io: IO_STATUS_BLOCK = undefined; var tmp_handle: HANDLE = undefined; var rc = ntdll.NtCreateFile( &tmp_handle, SYNCHRONIZE | DELETE, &attr, &io, null, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, create_options_flags, null, 0, ); switch (rc) { .SUCCESS => {}, .OBJECT_NAME_INVALID => unreachable, .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, .BAD_NETWORK_PATH => return error.NetworkNotFound, // \\server was not found .BAD_NETWORK_NAME => return error.NetworkNotFound, // \\server was found but \\server\share wasn't .INVALID_PARAMETER => unreachable, .FILE_IS_A_DIRECTORY => return error.IsDir, .NOT_A_DIRECTORY => return error.NotDir, .SHARING_VIOLATION => return error.FileBusy, .ACCESS_DENIED => return error.AccessDenied, .DELETE_PENDING => return, else => return unexpectedStatus(rc), } defer CloseHandle(tmp_handle); // FileDispositionInformationEx (and therefore FILE_DISPOSITION_POSIX_SEMANTICS and FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE) // are only supported on NTFS filesystems, so the version check on its own is only a partial solution. To support non-NTFS filesystems // like FAT32, we need to fallback to FileDispositionInformation if the usage of FileDispositionInformationEx gives // us INVALID_PARAMETER. // The same reasoning for win10_rs5 as in os.renameatW() applies (FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE requires >= win10_rs5). var need_fallback = true; if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs5)) { // Deletion with posix semantics if the filesystem supports it. var info = FILE_DISPOSITION_INFORMATION_EX{ .Flags = FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS | FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE, }; rc = ntdll.NtSetInformationFile( tmp_handle, &io, &info, @sizeOf(FILE_DISPOSITION_INFORMATION_EX), .FileDispositionInformationEx, ); switch (rc) { .SUCCESS => return, // INVALID_PARAMETER here means that the filesystem does not support FileDispositionInformationEx .INVALID_PARAMETER => {}, // For all other statuses, fall down to the switch below to handle them. else => need_fallback = false, } } if (need_fallback) { // Deletion with file pending semantics, which requires waiting or moving // files to get them removed (from here). var file_dispo = FILE_DISPOSITION_INFORMATION{ .DeleteFile = TRUE, }; rc = ntdll.NtSetInformationFile( tmp_handle, &io, &file_dispo, @sizeOf(FILE_DISPOSITION_INFORMATION), .FileDispositionInformation, ); } switch (rc) { .SUCCESS => {}, .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty, .INVALID_PARAMETER => unreachable, .CANNOT_DELETE => return error.AccessDenied, .MEDIA_WRITE_PROTECTED => return error.AccessDenied, .ACCESS_DENIED => return error.AccessDenied, else => return unexpectedStatus(rc), } }