Changeset 3682 for trunk/src/lib/nt/ntunlink.c
- Timestamp:
- Aug 13, 2025, 1:34:19 AM (4 weeks ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lib/nt/ntunlink.c
r3504 r3682 33 33 * Header Files * 34 34 *******************************************************************************/ 35 #include <io.h> /* for _get_osfhandle */ 35 36 #include "ntunlink.h" 36 37 37 38 #include "ntstuff.h" 38 39 #include "nthlp.h" 40 #include "nthlpmisc.h" 39 41 40 42 … … 82 84 83 85 84 static int birdUnlinkInternal(HANDLE hRoot, const char *pszFile, const wchar_t *pwszFile, int fReadOnlyToo, int fFast )86 static int birdUnlinkInternal(HANDLE hRoot, const char *pszFile, const wchar_t *pwszFile, int fReadOnlyToo, int fFast, int fRmDir) 85 87 { 86 88 MY_UNICODE_STRING NtPath; … … 108 110 if (fFast) 109 111 { 110 /* This uses FILE_DELETE_ON_CLOSE. Probably only suitable when in a hurry... */ 111 MY_OBJECT_ATTRIBUTES ObjAttr; 112 MyInitializeObjectAttributes(&ObjAttr, &NtPath, OBJ_CASE_INSENSITIVE, hRoot, NULL /*pSecAttr*/); 113 rcNt = g_pfnNtDeleteFile(&ObjAttr); 114 115 /* In case some file system does things differently than NTFS. */ 116 if (rcNt == STATUS_CANNOT_DELETE && fReadOnlyToo) 112 /* 113 * This uses FILE_DELETE_ON_CLOSE. 114 * 115 * It is only suitable if in a hurry and when 100% sure it is a regular file. 116 * It will follow symbolic links by default, so subject to races and abuse. 117 * 118 * If used on a directory and the directory isn't empty, it will return success 119 * instead of STATUS_CANNOT_DELETE. 120 * 121 * To stay out of trouble, we always use the OBJ_DONT_REPARSE flag here. This 122 * is a relative new addition (windows 10, build unknown), so if it ain't 123 * supported or we encounter a reparse object we just fall back to the regular 124 * deletion code. 125 */ 126 static int volatile s_iSupportsDontReparse = 0; 127 if (s_iSupportsDontReparse >= 0 && !fRmDir) 117 128 { 118 birdMakeWritable(hRoot, &NtPath); 129 MY_OBJECT_ATTRIBUTES ObjAttr; 130 MyInitializeObjectAttributes(&ObjAttr, &NtPath, OBJ_DONT_REPARSE | OBJ_CASE_INSENSITIVE, hRoot, NULL /*pSecAttr*/); 119 131 rcNt = g_pfnNtDeleteFile(&ObjAttr); 132 133 /* In case some file system does things differently than NTFS. */ 134 if (rcNt == STATUS_CANNOT_DELETE && fReadOnlyToo) 135 { 136 birdMakeWritable(hRoot, &NtPath); 137 rcNt = g_pfnNtDeleteFile(&ObjAttr); 138 } 139 140 /* Do fallback. */ 141 if (rcNt == STATUS_REPARSE_POINT_ENCOUNTERED) 142 fFast = 0; 143 else if (rcNt == STATUS_INVALID_PARAMETER) 144 { 145 s_iSupportsDontReparse = -1; 146 fFast = 0; 147 } 148 } 149 else 150 { 151 rcNt = STATUS_INVALID_PARAMETER; 152 fFast = 0; 120 153 } 121 154 } 122 else 155 156 if (!fFast) 123 157 { 124 /* Use the set information stuff. Probably more reliable. */ 158 /* 159 * Use the set information stuff. Here we can better control reparsing. 160 */ 125 161 HANDLE hFile; 126 162 for (;;) 127 163 { 164 MY_IO_STATUS_BLOCK Ios; 165 128 166 rcNt = birdOpenFileUniStr(hRoot, 129 167 &NtPath, … … 132 170 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 133 171 FILE_OPEN, 134 FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT, 172 (!fRmDir ? FILE_NON_DIRECTORY_FILE : FILE_DIRECTORY_FILE) 173 | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT, 135 174 OBJ_CASE_INSENSITIVE, 136 175 &hFile); 176 177 /* Windows distinguishes between symlinks to directories and to files, so 178 unlink(symlink-dir) will fail and we have to retry w/o the non-dir-file 179 flag and make sure it didn't turn into a pure directory. */ 180 if ( rcNt == STATUS_FILE_IS_A_DIRECTORY 181 && !fRmDir) 182 { 183 rcNt = birdOpenFileUniStr(hRoot, 184 &NtPath, 185 DELETE | FILE_READ_ATTRIBUTES | SYNCHRONIZE, 186 FILE_ATTRIBUTE_REPARSE_POINT, 187 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 188 FILE_OPEN, 189 FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT, 190 OBJ_CASE_INSENSITIVE, 191 &hFile); 192 if (MY_NT_SUCCESS(rcNt)) 193 { 194 MY_FILE_BASIC_INFORMATION BasicInfo; 195 memset(&BasicInfo, 0, sizeof(BasicInfo)); 196 197 Ios.Information = -1; 198 Ios.u.Status = -1; 199 200 rcNt = g_pfnNtQueryInformationFile(hFile, &Ios, &BasicInfo, sizeof(BasicInfo), MyFileBasicInformation); 201 if ( !MY_NT_SUCCESS(rcNt) 202 || !MY_NT_SUCCESS(Ios.u.Status) 203 || (BasicInfo.FileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY)) 204 == FILE_ATTRIBUTE_DIRECTORY) 205 { 206 birdCloseFile(hFile); 207 rcNt = STATUS_FILE_IS_A_DIRECTORY; 208 break; 209 } 210 } 211 } 212 137 213 if (MY_NT_SUCCESS(rcNt)) 138 214 { 139 215 MY_FILE_DISPOSITION_INFORMATION DispInfo; 140 MY_IO_STATUS_BLOCK Ios;141 142 216 DispInfo.DeleteFile = TRUE; 143 217 … … 161 235 if (MY_NT_SUCCESS(rcNt)) 162 236 rc = 0; 237 else if (rcNt == STATUS_SHARING_VIOLATION && fRmDir) 238 rc = birdSetErrnoToDirNotEmpty(); /* probably the case... */ 163 239 else 164 240 rc = birdSetErrnoFromNt(rcNt); … … 168 244 169 245 246 /* 247 * unlink: 248 */ 249 170 250 int birdUnlink(const char *pszFile) 171 251 { 172 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 0 /*fReadOnlyToo*/, 0 /*fFast*/ );252 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 0 /*fRmDir*/); 173 253 } 174 254 … … 176 256 int birdUnlinkW(const wchar_t *pwszFile) 177 257 { 178 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pwszFile*/, pwszFile, 0 /*fReadOnlyToo*/, 0 /*fFast*/ );258 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pwszFile*/, pwszFile, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 0 /*fRmDir*/); 179 259 } 180 260 … … 182 262 int birdUnlinkEx(void *hRoot, const char *pszFile) 183 263 { 184 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 0 /*fReadOnlyToo*/, 0 /*fFast*/ );264 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 0 /*fRmDir*/); 185 265 } 186 266 … … 188 268 int birdUnlinkExW(void *hRoot, const wchar_t *pwszFile) 189 269 { 190 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 0 /*fReadOnlyToo*/, 0 /*fFast*/ );270 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 0 /*fRmDir*/); 191 271 } 192 272 … … 194 274 int birdUnlinkForced(const char *pszFile) 195 275 { 196 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/ );276 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 0 /*fRmDir*/); 197 277 } 198 278 … … 200 280 int birdUnlinkForcedW(const wchar_t *pwszFile) 201 281 { 202 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 0 /*fFast*/ );282 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 0 /*fRmDir*/); 203 283 } 204 284 … … 206 286 int birdUnlinkForcedEx(void *hRoot, const char *pszFile) 207 287 { 208 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/ );288 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 0 /*fRmDir*/); 209 289 } 210 290 … … 212 292 int birdUnlinkForcedExW(void *hRoot, const wchar_t *pwszFile) 213 293 { 214 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 0 /*fFast*/ );294 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 0 /*fRmDir*/); 215 295 } 216 296 … … 218 298 int birdUnlinkForcedFast(const char *pszFile) 219 299 { 220 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 1 /*fFast*/ );300 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 1 /*fFast*/, 0 /*fRmDir*/); 221 301 } 222 302 … … 224 304 int birdUnlinkForcedFastW(const wchar_t *pwszFile) 225 305 { 226 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 1 /*fFast*/ );306 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 1 /*fFast*/, 0 /*fRmDir*/); 227 307 } 228 308 … … 230 310 int birdUnlinkForcedFastEx(void *hRoot, const char *pszFile) 231 311 { 232 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 1 /*fFast*/ );312 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 1 /*fFast*/, 0 /*fRmDir*/); 233 313 } 234 314 … … 236 316 int birdUnlinkForcedFastExW(void *hRoot, const wchar_t *pwszFile) 237 317 { 238 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 1 /*fFast*/); 239 } 240 318 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 1 /*fFast*/, 0 /*fRmDir*/); 319 } 320 321 322 /* 323 * rmdir 324 */ 325 326 int birdRmDir(const char *pszFile) 327 { 328 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/); 329 } 330 331 332 int birdRmDirW(const wchar_t *pwszFile) 333 { 334 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pwszFile*/, pwszFile, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/); 335 } 336 337 338 int birdRmDirEx(void *hRoot, const char *pszFile) 339 { 340 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/); 341 } 342 343 344 int birdRmDirExW(void *hRoot, const wchar_t *pwszFile) 345 { 346 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/); 347 } 348 349 350 int birdRmDirForced(const char *pszFile) 351 { 352 return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/); 353 } 354 355 356 int birdRmDirForcedW(const wchar_t *pwszFile) 357 { 358 return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/); 359 } 360 361 362 int birdRmDirForcedEx(void *hRoot, const char *pszFile) 363 { 364 return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/); 365 } 366 367 368 int birdRmDirForcedExW(void *hRoot, const wchar_t *pwszFile) 369 { 370 return birdUnlinkInternal((HANDLE)hRoot, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/); 371 } 372 373 374 /** 375 * Implements unlinkat(). 376 */ 377 int birdUnlinkAt(int fdDir, const char *pszPath, int fFlags) 378 { 379 HANDLE hDirRoot; 380 381 /** @todo validate input. */ 382 fFlags &= AT_REMOVEDIR; 383 384 /* 385 * Check the path its effectively a AT_FDCWD call. 386 */ 387 if (fdDir != AT_FDCWD) 388 { 389 if (IS_SLASH(pszPath[0])) 390 { 391 if (IS_SLASH(pszPath[1]) && !IS_SLASH(pszPath[2]) && pszPath[2] != '\0') 392 fdDir = AT_FDCWD; 393 } 394 else if (IS_ALPHA(pszPath[0]) && pszPath[1] == ':') 395 { 396 if (IS_SLASH(pszPath[2])) 397 fdDir = AT_FDCWD; 398 else 399 /* 400 * Drive letter relative path like "C:kernel32.dll". 401 * We could try use fdDir as the CWD here if it refers to the same drive, 402 * however that's can be implemented later... 403 */ 404 fdDir = AT_FDCWD; 405 } 406 } 407 408 /* 409 * Determine hDirRoot. 410 */ 411 if (fdDir == AT_FDCWD) 412 hDirRoot = NULL; 413 else 414 { 415 hDirRoot = (HANDLE)_get_osfhandle(fdDir); 416 if (hDirRoot == INVALID_HANDLE_VALUE || hDirRoot == NULL) 417 return birdSetErrnoToBadFileNo(); 418 } 419 420 return birdUnlinkInternal(hDirRoot, pszPath, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/, !!fFlags /*fRmDir*/); 421 } 422
Note:
See TracChangeset
for help on using the changeset viewer.