source: trunk/src/lib/nt/ntunlink.c

Last change on this file was 3504, checked in by bird, 4 years ago

ntunlink.c: Fixed deleteing read-only files. Respect the fReadOnlyToo parameter.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.9 KB
RevLine 
[2713]1/* $Id: ntunlink.c 3504 2021-12-15 22:50:14Z bird $ */
2/** @file
3 * MSC + NT unlink and variations.
4 */
5
6/*
[3060]7 * Copyright (c) 2005-2017 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
[2713]8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * IN THE SOFTWARE.
26 *
27 * Alternatively, the content of this file may be used under the terms of the
28 * GPL version 2 or later, or LGPL version 2.1 or later.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
[3060]35#include "ntunlink.h"
[2713]36
37#include "ntstuff.h"
38#include "nthlp.h"
39
40
[3386]41static MY_NTSTATUS birdMakeWritable(HANDLE hRoot, MY_UNICODE_STRING *pNtPath)
[2713]42{
43 MY_NTSTATUS rcNt;
44 HANDLE hFile;
45
[3386]46 rcNt = birdOpenFileUniStr(hRoot,
[2985]47 pNtPath,
[2713]48 FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
49 FILE_ATTRIBUTE_NORMAL,
50 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
51 FILE_OPEN,
52 FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
53 OBJ_CASE_INSENSITIVE,
54 &hFile);
55 if (MY_NT_SUCCESS(rcNt))
56 {
57 MY_FILE_BASIC_INFORMATION BasicInfo;
58 MY_IO_STATUS_BLOCK Ios;
59 DWORD dwAttr;
60
61 Ios.Information = -1;
62 Ios.u.Status = -1;
[3388]63 memset(&BasicInfo, 0, sizeof(BasicInfo));
[2713]64 rcNt = g_pfnNtQueryInformationFile(hFile, &Ios, &BasicInfo, sizeof(BasicInfo), MyFileBasicInformation);
65
[3504]66 if (MY_NT_SUCCESS(rcNt) && MY_NT_SUCCESS(Ios.u.Status) && BasicInfo.FileAttributes != FILE_ATTRIBUTE_READONLY)
[2713]67 dwAttr = BasicInfo.FileAttributes & ~FILE_ATTRIBUTE_READONLY;
68 else
69 dwAttr = FILE_ATTRIBUTE_NORMAL;
70 memset(&BasicInfo, 0, sizeof(BasicInfo));
71 BasicInfo.FileAttributes = dwAttr;
72
73 Ios.Information = -1;
74 Ios.u.Status = -1;
75 rcNt = g_pfnNtSetInformationFile(hFile, &Ios, &BasicInfo, sizeof(BasicInfo), MyFileBasicInformation);
76
77 birdCloseFile(hFile);
78 }
79
80 return rcNt;
81}
82
83
[3009]84static int birdUnlinkInternal(HANDLE hRoot, const char *pszFile, const wchar_t *pwszFile, int fReadOnlyToo, int fFast)
[2713]85{
86 MY_UNICODE_STRING NtPath;
87 int rc;
88
[2997]89 if (hRoot == INVALID_HANDLE_VALUE)
90 hRoot = NULL;
91 if (hRoot == NULL)
[3009]92 {
93 if (pwszFile)
94 rc = birdDosToNtPathW(pwszFile, &NtPath);
95 else
96 rc = birdDosToNtPath(pszFile, &NtPath);
97 }
[2997]98 else
[3009]99 {
100 if (pwszFile)
101 rc = birdDosToRelativeNtPathW(pwszFile, &NtPath);
102 else
103 rc = birdDosToRelativeNtPath(pszFile, &NtPath);
104 }
[2713]105 if (rc == 0)
106 {
107 MY_NTSTATUS rcNt;
108 if (fFast)
109 {
110 /* This uses FILE_DELETE_ON_CLOSE. Probably only suitable when in a hurry... */
111 MY_OBJECT_ATTRIBUTES ObjAttr;
[2997]112 MyInitializeObjectAttributes(&ObjAttr, &NtPath, OBJ_CASE_INSENSITIVE, hRoot, NULL /*pSecAttr*/);
[2713]113 rcNt = g_pfnNtDeleteFile(&ObjAttr);
114
115 /* In case some file system does things differently than NTFS. */
[3504]116 if (rcNt == STATUS_CANNOT_DELETE && fReadOnlyToo)
[2713]117 {
[3386]118 birdMakeWritable(hRoot, &NtPath);
[2713]119 rcNt = g_pfnNtDeleteFile(&ObjAttr);
120 }
121 }
122 else
123 {
124 /* Use the set information stuff. Probably more reliable. */
125 HANDLE hFile;
126 for (;;)
127 {
[2997]128 rcNt = birdOpenFileUniStr(hRoot,
[2985]129 &NtPath,
[3126]130 DELETE | SYNCHRONIZE,
[2713]131 FILE_ATTRIBUTE_NORMAL,
132 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
133 FILE_OPEN,
134 FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT,
135 OBJ_CASE_INSENSITIVE,
136 &hFile);
137 if (MY_NT_SUCCESS(rcNt))
138 {
139 MY_FILE_DISPOSITION_INFORMATION DispInfo;
140 MY_IO_STATUS_BLOCK Ios;
141
142 DispInfo.DeleteFile = TRUE;
143
144 Ios.Information = -1;
145 Ios.u.Status = -1;
146
147 rcNt = g_pfnNtSetInformationFile(hFile, &Ios, &DispInfo, sizeof(DispInfo), MyFileDispositionInformation);
148
149 birdCloseFile(hFile);
150 }
[3504]151 if (rcNt != STATUS_CANNOT_DELETE || !fReadOnlyToo)
[2713]152 break;
153
[3504]154 fReadOnlyToo = 0;
[3386]155 birdMakeWritable(hRoot, &NtPath);
[2713]156 }
157 }
158
159 birdFreeNtPath(&NtPath);
160
161 if (MY_NT_SUCCESS(rcNt))
162 rc = 0;
163 else
164 rc = birdSetErrnoFromNt(rcNt);
165 }
166 return rc;
167}
168
169
170int birdUnlink(const char *pszFile)
171{
[3009]172 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 0 /*fReadOnlyToo*/, 0 /*fFast*/);
[2713]173}
174
175
[3009]176int birdUnlinkW(const wchar_t *pwszFile)
177{
178 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pwszFile*/, pwszFile, 0 /*fReadOnlyToo*/, 0 /*fFast*/);
179}
180
181
[2997]182int birdUnlinkEx(void *hRoot, const char *pszFile)
183{
[3009]184 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 0 /*fReadOnlyToo*/, 0 /*fFast*/);
[2997]185}
186
187
[3009]188int birdUnlinkExW(void *hRoot, const wchar_t *pwszFile)
189{
190 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 0 /*fReadOnlyToo*/, 0 /*fFast*/);
191}
192
193
[2713]194int birdUnlinkForced(const char *pszFile)
195{
[3009]196 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/);
[2713]197}
198
199
[3009]200int birdUnlinkForcedW(const wchar_t *pwszFile)
201{
202 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 0 /*fFast*/);
203}
204
205
[2997]206int birdUnlinkForcedEx(void *hRoot, const char *pszFile)
207{
[3009]208 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/);
[2997]209}
210
211
[3009]212int birdUnlinkForcedExW(void *hRoot, const wchar_t *pwszFile)
213{
214 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 0 /*fFast*/);
215}
216
217
[2713]218int birdUnlinkForcedFast(const char *pszFile)
219{
[3009]220 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 1 /*fFast*/);
[2713]221}
222
[2997]223
[3009]224int birdUnlinkForcedFastW(const wchar_t *pwszFile)
225{
226 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 1 /*fFast*/);
227}
228
229
[2997]230int birdUnlinkForcedFastEx(void *hRoot, const char *pszFile)
231{
[3009]232 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 1 /*fFast*/);
[2997]233}
234
[3009]235
236int birdUnlinkForcedFastExW(void *hRoot, const wchar_t *pwszFile)
237{
238 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 1 /*fFast*/);
239}
240
Note: See TracBrowser for help on using the repository browser.