Changeset 3682 for trunk/src/lib/nt


Ignore:
Timestamp:
Aug 13, 2025, 1:34:19 AM (4 weeks ago)
Author:
bird
Message:

lib/nt,kmk: Fixed around rm/unlink semantics and general support for long file names in lib/nt.

Location:
trunk/src/lib/nt
Files:
4 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/lib/nt/nthlp.h

    r3337 r3682  
    4040void        birdResolveImportsWorker(void);
    4141extern int  g_fResolvedNtImports;
     42extern OSVERSIONINFOEXW g_NtVerInfo;
    4243
    4344void       *birdTmpAlloc(size_t cb);
     
    5354int         birdSetErrnoToInvalidArg(void);
    5455int         birdSetErrnoToBadFileNo(void);
     56int         birdSetErrnoToDirNotEmpty(void);
    5557
    5658HANDLE      birdOpenFile(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
  • trunk/src/lib/nt/nthlpcore.c

    r3534 r3682  
    6060MY_NTSTATUS (WINAPI *g_pfnNtSetInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FILE_INFORMATION_CLASS);
    6161BOOLEAN     (WINAPI *g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *);
     62BOOLEAN     (WINAPI *g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *);
     63MY_NTSTATUS (WINAPI *g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *,
     64                                                                       MY_RTL_RELATIVE_NAME_U *);
    6265MY_NTSTATUS (WINAPI *g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN);
    6366MY_NTSTATUS (WINAPI *g_pfnRtlUnicodeStringToAnsiString)(MY_ANSI_STRING *, MY_UNICODE_STRING *, BOOLEAN);
     
    6871VOID        (WINAPI *g_pfnRtlAcquirePebLock)(VOID);
    6972VOID        (WINAPI *g_pfnRtlReleasePebLock)(VOID);
     73MY_NTSTATUS (WINAPI *g_pfnRtlGetVersion)(OSVERSIONINFOEXW *);
     74
    7075
    7176static struct
     
    7378    FARPROC    *ppfn;
    7479    const char *pszName;
     80    int         fOptional;
    7581} const g_apfnDynamicNtdll[] =
    7682{
    77     { (FARPROC *)&g_pfnNtClose,                         "NtClose" },
    78     { (FARPROC *)&g_pfnNtCreateFile,                    "NtCreateFile" },
    79     { (FARPROC *)&g_pfnNtDeleteFile,                    "NtDeleteFile" },
    80     { (FARPROC *)&g_pfnNtDuplicateObject,               "NtDuplicateObject" },
    81     { (FARPROC *)&g_pfnNtReadFile,                      "NtReadFile" },
    82     { (FARPROC *)&g_pfnNtQueryInformationFile,          "NtQueryInformationFile" },
    83     { (FARPROC *)&g_pfnNtQueryVolumeInformationFile,    "NtQueryVolumeInformationFile" },
    84     { (FARPROC *)&g_pfnNtQueryDirectoryFile,            "NtQueryDirectoryFile" },
    85     { (FARPROC *)&g_pfnNtQueryAttributesFile,           "NtQueryAttributesFile" },
    86     { (FARPROC *)&g_pfnNtQueryFullAttributesFile,       "NtQueryFullAttributesFile" },
    87     { (FARPROC *)&g_pfnNtSetInformationFile,            "NtSetInformationFile" },
    88     { (FARPROC *)&g_pfnRtlDosPathNameToNtPathName_U,    "RtlDosPathNameToNtPathName_U" },
    89     { (FARPROC *)&g_pfnRtlAnsiStringToUnicodeString,    "RtlAnsiStringToUnicodeString" },
    90     { (FARPROC *)&g_pfnRtlUnicodeStringToAnsiString,    "RtlUnicodeStringToAnsiString" },
    91     { (FARPROC *)&g_pfnRtlEqualUnicodeString,           "RtlEqualUnicodeString" },
    92     { (FARPROC *)&g_pfnRtlEqualString,                  "RtlEqualString" },
    93     { (FARPROC *)&g_pfnRtlUpperChar,                    "RtlUpperChar" },
    94     { (FARPROC *)&g_pfnRtlNtStatusToDosError,           "RtlNtStatusToDosError" },
    95     { (FARPROC *)&g_pfnRtlAcquirePebLock,               "RtlAcquirePebLock" },
    96     { (FARPROC *)&g_pfnRtlReleasePebLock,               "RtlReleasePebLock" },
     83    { (FARPROC *)&g_pfnNtClose,                                     "NtClose",                                      0 },
     84    { (FARPROC *)&g_pfnNtCreateFile,                                "NtCreateFile",                                 0 },
     85    { (FARPROC *)&g_pfnNtDeleteFile,                                "NtDeleteFile",                                 0 },
     86    { (FARPROC *)&g_pfnNtDuplicateObject,                           "NtDuplicateObject",                            0 },
     87    { (FARPROC *)&g_pfnNtReadFile,                                  "NtReadFile",                                   0 },
     88    { (FARPROC *)&g_pfnNtQueryInformationFile,                      "NtQueryInformationFile",                       0 },
     89    { (FARPROC *)&g_pfnNtQueryVolumeInformationFile,                "NtQueryVolumeInformationFile",                 0 },
     90    { (FARPROC *)&g_pfnNtQueryDirectoryFile,                        "NtQueryDirectoryFile",                         0 },
     91    { (FARPROC *)&g_pfnNtQueryAttributesFile,                       "NtQueryAttributesFile",                        0 },
     92    { (FARPROC *)&g_pfnNtQueryFullAttributesFile,                   "NtQueryFullAttributesFile",                    0 },
     93    { (FARPROC *)&g_pfnNtSetInformationFile,                        "NtSetInformationFile",                         0 },
     94    { (FARPROC *)&g_pfnRtlDosPathNameToNtPathName_U,                "RtlDosPathNameToNtPathName_U",                 0 },
     95    { (FARPROC *)&g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus, "RtlDosLongPathNameToNtPathName_U_WithStatus",  1 },
     96    { (FARPROC *)&g_pfnRtlAnsiStringToUnicodeString,                "RtlAnsiStringToUnicodeString",                 0 },
     97    { (FARPROC *)&g_pfnRtlUnicodeStringToAnsiString,                "RtlUnicodeStringToAnsiString",                 0 },
     98    { (FARPROC *)&g_pfnRtlEqualUnicodeString,                       "RtlEqualUnicodeString",                        0 },
     99    { (FARPROC *)&g_pfnRtlEqualString,                              "RtlEqualString",                               0 },
     100    { (FARPROC *)&g_pfnRtlUpperChar,                                "RtlUpperChar",                                 0 },
     101    { (FARPROC *)&g_pfnRtlNtStatusToDosError,                       "RtlNtStatusToDosError",                        0 },
     102    { (FARPROC *)&g_pfnRtlAcquirePebLock,                           "RtlAcquirePebLock",                            0 },
     103    { (FARPROC *)&g_pfnRtlReleasePebLock,                           "RtlReleasePebLock",                            0 },
     104    { (FARPROC *)&g_pfnRtlGetVersion,                               "RtlGetVersion",                                1 },
    97105};
    98106/** Set to 1 if we've successfully resolved the imports, otherwise 0. */
    99107int g_fResolvedNtImports = 0;
    100108
     109/** Windows / NT version info. */
     110OSVERSIONINFOEXW g_NtVerInfo;
    101111
    102112
    103113void birdResolveImportsWorker(void)
    104114{
     115    /* Load the imports. */
    105116    HMODULE     hMod = LoadLibraryW(L"ntdll.dll");
    106117    int         i    = sizeof(g_apfnDynamicNtdll) / sizeof(g_apfnDynamicNtdll[0]);
     
    110121        FARPROC     pfn;
    111122        *g_apfnDynamicNtdll[i].ppfn = pfn = GetProcAddress(hMod, pszSym);
    112         if (!pfn)
     123        if (!pfn && !g_apfnDynamicNtdll[i].fOptional)
    113124        {
    114125            /* Write short message and die. */
     
    124135    }
    125136
     137    /* Get the version. */
     138#pragma warning(push)
     139#pragma warning(disable:4996)
     140    g_NtVerInfo.dwOSVersionInfoSize = sizeof(g_NtVerInfo);
     141    GetVersionExW((OSVERSIONINFOW *)&g_NtVerInfo);
     142#pragma warning(pop)
     143    if (g_pfnRtlGetVersion)
     144        g_pfnRtlGetVersion(&g_NtVerInfo);
     145
     146    /* Mark everything as done. */
    126147    g_fResolvedNtImports = 1;
    127148}
     
    480501}
    481502
     503
     504int birdSetErrnoToDirNotEmpty(void)
     505{
     506    errno = ENOTEMPTY;
     507    return -1;
     508}
     509
  • trunk/src/lib/nt/nthlpfs.c

    r3223 r3682  
    149149             * Convert the wide DOS path to an NT path.
    150150             */
    151             if (g_pfnRtlDosPathNameToNtPathName_U(wszTmp, pNtPath, NULL, FALSE))
     151            if (g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus)
     152            {
     153                rcNt = g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus(wszTmp, pNtPath, NULL, NULL);
     154                if (MY_NT_SUCCESS(rcNt))
     155                    return 0;
     156            }
     157            else if (g_pfnRtlDosPathNameToNtPathName_U(wszTmp, pNtPath, NULL, NULL))
    152158                return 0;
     159            else
     160                rcNt = -1;
    153161        }
    154         rcNt = -1;
     162        else
     163            rcNt = -1;
    155164    }
    156165    return birdSetErrnoFromNt(rcNt);
     
    168177     * Convert the wide DOS path to an NT path.
    169178     */
    170     if (g_pfnRtlDosPathNameToNtPathName_U(pwszPath, pNtPath, NULL, FALSE))
     179    if (g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus)
     180    {
     181        MY_NTSTATUS rcNt = g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus(pwszPath, pNtPath, NULL, NULL);
     182        if (MY_NT_SUCCESS(rcNt))
     183            return 0;
     184        return birdSetErrnoFromNt(rcNt);
     185    }
     186    if (g_pfnRtlDosPathNameToNtPathName_U(pwszPath, pNtPath, NULL, NULL))
    171187        return 0;
    172188    return birdSetErrnoFromNt(STATUS_NO_MEMORY);
  • trunk/src/lib/nt/ntopenat.c

    r3601 r3682  
    4040#include "ntstuff.h"
    4141#include "nthlp.h"
     42#include "nthlpmisc.h"
    4243#include "ntopenat.h"
    4344#include "ntstat.h"
    44 
    45 
    46 #define IS_ALPHA(ch) ( ((ch) >= 'A' && (ch) <= 'Z') || ((ch) >= 'a' && (ch) <= 'z') )
    47 #define IS_SLASH(ch) ((ch) == '\\' || (ch) == '/')
    48 
    4945
    5046
     
    9591
    9692
     93/**
     94 * Implements open.
     95 */
    9796int birdOpen(const char *pszPath, int fFlags, ...)
    9897{
     
    160159}
    161160
    162 
  • trunk/src/lib/nt/ntopenat.h

    r3533 r3682  
    3333
    3434#include "nttypes.h"
     35#include "ntat.h"
    3536
     37extern int birdOpen(const char *pszPath, int fFlags, ...);
    3638extern int birdOpenAt(int fdDir, const char *pszPath, int fFlags, ...);
    3739
    3840#define openat                      birdOpenAt
    3941
    40 #define AT_FDCWD        (-987654321)
    41 
    4242#endif
    4343
  • trunk/src/lib/nt/ntstuff.h

    r3644 r3682  
    558558extern MY_NTSTATUS (WINAPI * g_pfnNtSetInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FILE_INFORMATION_CLASS);
    559559extern BOOLEAN     (WINAPI * g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *);
     560extern MY_NTSTATUS (WINAPI * g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *,
     561                                                                               MY_RTL_RELATIVE_NAME_U *);
    560562extern MY_NTSTATUS (WINAPI * g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN);
    561563extern MY_NTSTATUS (WINAPI * g_pfnRtlUnicodeStringToAnsiString)(MY_ANSI_STRING *, MY_UNICODE_STRING *, BOOLEAN);
  • trunk/src/lib/nt/ntunlink.c

    r3504 r3682  
    3333*   Header Files                                                               *
    3434*******************************************************************************/
     35#include <io.h>  /* for _get_osfhandle */
    3536#include "ntunlink.h"
    3637
    3738#include "ntstuff.h"
    3839#include "nthlp.h"
     40#include "nthlpmisc.h"
    3941
    4042
     
    8284
    8385
    84 static int birdUnlinkInternal(HANDLE hRoot, const char *pszFile, const wchar_t *pwszFile, int fReadOnlyToo, int fFast)
     86static int birdUnlinkInternal(HANDLE hRoot, const char *pszFile, const wchar_t *pwszFile, int fReadOnlyToo, int fFast, int fRmDir)
    8587{
    8688    MY_UNICODE_STRING   NtPath;
     
    108110        if (fFast)
    109111        {
    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)
    117128            {
    118                 birdMakeWritable(hRoot, &NtPath);
     129                MY_OBJECT_ATTRIBUTES ObjAttr;
     130                MyInitializeObjectAttributes(&ObjAttr, &NtPath, OBJ_DONT_REPARSE | OBJ_CASE_INSENSITIVE, hRoot, NULL /*pSecAttr*/);
    119131                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;
    120153            }
    121154        }
    122         else
     155
     156        if (!fFast)
    123157        {
    124             /* Use the set information stuff. Probably more reliable. */
     158            /*
     159             * Use the set information stuff. Here we can better control reparsing.
     160             */
    125161            HANDLE hFile;
    126162            for (;;)
    127163            {
     164                MY_IO_STATUS_BLOCK Ios;
     165
    128166                rcNt = birdOpenFileUniStr(hRoot,
    129167                                          &NtPath,
     
    132170                                          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
    133171                                          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,
    135174                                          OBJ_CASE_INSENSITIVE,
    136175                                          &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
    137213                if (MY_NT_SUCCESS(rcNt))
    138214                {
    139215                    MY_FILE_DISPOSITION_INFORMATION DispInfo;
    140                     MY_IO_STATUS_BLOCK              Ios;
    141 
    142216                    DispInfo.DeleteFile = TRUE;
    143217
     
    161235        if (MY_NT_SUCCESS(rcNt))
    162236            rc = 0;
     237        else if (rcNt == STATUS_SHARING_VIOLATION && fRmDir)
     238            rc = birdSetErrnoToDirNotEmpty(); /* probably the case... */
    163239        else
    164240            rc = birdSetErrnoFromNt(rcNt);
     
    168244
    169245
     246/*
     247 * unlink:
     248 */
     249
    170250int birdUnlink(const char *pszFile)
    171251{
    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*/);
    173253}
    174254
     
    176256int birdUnlinkW(const wchar_t *pwszFile)
    177257{
    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*/);
    179259}
    180260
     
    182262int birdUnlinkEx(void *hRoot, const char *pszFile)
    183263{
    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*/);
    185265}
    186266
     
    188268int birdUnlinkExW(void *hRoot, const wchar_t *pwszFile)
    189269{
    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*/);
    191271}
    192272
     
    194274int birdUnlinkForced(const char *pszFile)
    195275{
    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*/);
    197277}
    198278
     
    200280int birdUnlinkForcedW(const wchar_t *pwszFile)
    201281{
    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*/);
    203283}
    204284
     
    206286int birdUnlinkForcedEx(void *hRoot, const char *pszFile)
    207287{
    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*/);
    209289}
    210290
     
    212292int birdUnlinkForcedExW(void *hRoot, const wchar_t *pwszFile)
    213293{
    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*/);
    215295}
    216296
     
    218298int birdUnlinkForcedFast(const char *pszFile)
    219299{
    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*/);
    221301}
    222302
     
    224304int birdUnlinkForcedFastW(const wchar_t *pwszFile)
    225305{
    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*/);
    227307}
    228308
     
    230310int birdUnlinkForcedFastEx(void *hRoot, const char *pszFile)
    231311{
    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*/);
    233313}
    234314
     
    236316int birdUnlinkForcedFastExW(void *hRoot, const wchar_t *pwszFile)
    237317{
    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
     326int birdRmDir(const char *pszFile)
     327{
     328    return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/);
     329}
     330
     331
     332int birdRmDirW(const wchar_t *pwszFile)
     333{
     334    return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pwszFile*/, pwszFile, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/);
     335}
     336
     337
     338int birdRmDirEx(void *hRoot, const char *pszFile)
     339{
     340    return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 0 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/);
     341}
     342
     343
     344int 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
     350int birdRmDirForced(const char *pszFile)
     351{
     352    return birdUnlinkInternal(NULL /*hRoot*/, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/);
     353}
     354
     355
     356int birdRmDirForcedW(const wchar_t *pwszFile)
     357{
     358    return birdUnlinkInternal(NULL /*hRoot*/, NULL /*pszFile*/, pwszFile, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/);
     359}
     360
     361
     362int birdRmDirForcedEx(void *hRoot, const char *pszFile)
     363{
     364    return birdUnlinkInternal((HANDLE)hRoot, pszFile, NULL /*pwszFile*/, 1 /*fReadOnlyToo*/, 0 /*fFast*/, 1 /*fRmDir*/);
     365}
     366
     367
     368int 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 */
     377int 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
  • trunk/src/lib/nt/ntunlink.h

    r3060 r3682  
    3333
    3434#include "nttypes.h"
     35#include "ntat.h"
    3536#include <wchar.h>
    3637
     
    4849int birdUnlinkForcedFastExW(void *hRoot, const wchar_t *pwszFile);
    4950
     51int birdRmDir(const char *pszFile);
     52int birdRmDirW(const wchar_t *pwszFile);
     53int birdRmDirEx(void *hRoot, const char *pszFile);
     54int birdRmDirExW(void *hRoot, const wchar_t *pwszFile);
     55int birdRmDirForced(const char *pszFile);
     56int birdRmDirForcedW(const wchar_t *pwszFile);
     57int birdRmDirForcedEx(void *hRoot, const char *pszFile);
     58int birdRmDirForcedExW(void *hRoot, const wchar_t *pszFile);
     59
     60#define AT_REMOVEDIR 1
     61int birdUnlinkAt(int fdDir, const char *pszPath, int fFlags);
     62
    5063#undef  unlink
    5164#define unlink(a_pszPath)     birdUnlinkForced(a_pszPath)
    5265
     66#undef  rmdir
     67#define rmdir(a_pszPath)      birdRmDirForced(a_pszPath)
     68
     69#undef  unlinkat
     70#define unlinkat(a_fdDir, a_pszPath, a_fFlags) birdUnlinkAt(a_fdDir, a_pszPath, a_fFlags)
     71
    5372#endif
    5473
Note: See TracChangeset for help on using the changeset viewer.