dir.cpp revision 69758b10eaf375c6a792694a3881bc17cd58a1a3
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync/* $Id$ */
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync/** @file
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * IPRT - Directory Manipulation.
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync */
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync *
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * available from http://www.virtualbox.org. This file is free software;
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * you can redistribute it and/or modify it under the terms of the GNU
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * General Public License (GPL) as published by the Free Software
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync *
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * The contents of this file may alternatively be used under the terms
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * of the Common Development and Distribution License Version 1.0
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * VirtualBox OSE distribution, in which case the provisions of the
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * CDDL are applicable instead of those of the GPL.
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync *
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * You may elect to license modified versions of this file under the
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync * terms and conditions of either the GPL or the CDDL or both.
4346537134a6c1454fc906711dbe4e987ebe9f33vboxsync *
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * additional information or have any questions.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync */
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync/*******************************************************************************
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync* Header Files *
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync*******************************************************************************/
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync#define LOG_GROUP RTLOGGROUP_DIR
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#ifdef RT_OS_WINDOWS /* PORTME: Assumes everyone else is using dir-posix.cpp */
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync# include <Windows.h>
7af218a7441de38fc9e814919db04bae3e917664vboxsync#else
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync# include <dirent.h>
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync# include <unistd.h>
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync# include <limits.h>
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#endif
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#include <iprt/dir.h>
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#include <iprt/file.h>
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#include <iprt/path.h>
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#include <iprt/alloc.h>
044af0d1e6474076366759db86f101778c5f20ccvboxsync#include <iprt/log.h>
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#include <iprt/param.h>
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#include <iprt/string.h>
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#include <iprt/err.h>
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#include <iprt/assert.h>
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#include <iprt/uni.h>
044af0d1e6474076366759db86f101778c5f20ccvboxsync#include "internal/fs.h"
044af0d1e6474076366759db86f101778c5f20ccvboxsync#include "internal/dir.h"
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsyncstatic DECLCALLBACK(bool) rtDirFilterWinNtMatch(PRTDIR pDir, const char *pszName);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsyncstatic DECLCALLBACK(bool) rtDirFilterWinNtMatchNoWildcards(PRTDIR pDir, const char *pszName);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsyncDECLINLINE(bool) rtDirFilterWinNtMatchEon(PCRTUNICP puszFilter);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsyncstatic bool rtDirFilterWinNtMatchDosStar(unsigned iDepth, RTUNICP uc, const char *pszNext, PCRTUNICP puszFilter);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsyncstatic bool rtDirFilterWinNtMatchStar(unsigned iDepth, RTUNICP uc, const char *pszNext, PCRTUNICP puszFilter);
044af0d1e6474076366759db86f101778c5f20ccvboxsyncstatic bool rtDirFilterWinNtMatchBase(unsigned iDepth, const char *pszName, PCRTUNICP puszFilter);
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsyncRTDECL(int) RTDirCreateFullPath(const char *pszPath, RTFMODE fMode)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync{
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /*
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Resolve the path.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync char szAbsPath[RTPATH_MAX];
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync int rc = RTPathAbs(pszPath, szAbsPath, sizeof(szAbsPath));
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (RT_FAILURE(rc))
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return rc;
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Iterate the path components making sure each of them exists.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* skip volume name */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync char *psz = &szAbsPath[rtPathVolumeSpecLen(szAbsPath)];
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* skip the root slash if any */
044af0d1e6474076366759db86f101778c5f20ccvboxsync if ( psz[0] == '/'
044af0d1e6474076366759db86f101778c5f20ccvboxsync#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync || psz[0] == '\\'
044af0d1e6474076366759db86f101778c5f20ccvboxsync#endif
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync )
044af0d1e6474076366759db86f101778c5f20ccvboxsync psz++;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync /* iterate over path components. */
de6e321f351aa489a6a62bed474390a0056e8093vboxsync do
de6e321f351aa489a6a62bed474390a0056e8093vboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* the next component is NULL, stop iterating */
de6e321f351aa489a6a62bed474390a0056e8093vboxsync if (!*psz)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync break;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync psz = strpbrk(psz, "\\/");
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync#else
de6e321f351aa489a6a62bed474390a0056e8093vboxsync psz = strchr(psz, '/');
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#endif
de6e321f351aa489a6a62bed474390a0056e8093vboxsync if (psz)
de6e321f351aa489a6a62bed474390a0056e8093vboxsync *psz = '\0';
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync /*
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * ASSUME that RTDirCreate will return VERR_ALREADY_EXISTS and not VERR_ACCESS_DENIED in those cases
de6e321f351aa489a6a62bed474390a0056e8093vboxsync * where the directory exists but we don't have write access to the parent directory.
de6e321f351aa489a6a62bed474390a0056e8093vboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync rc = RTDirCreate(szAbsPath, fMode);
de6e321f351aa489a6a62bed474390a0056e8093vboxsync if (rc == VERR_ALREADY_EXISTS)
044af0d1e6474076366759db86f101778c5f20ccvboxsync rc = VINF_SUCCESS;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (!psz)
044af0d1e6474076366759db86f101778c5f20ccvboxsync break;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync *psz++ = RTPATH_DELIMITER;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync } while (RT_SUCCESS(rc));
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync return rc;
044af0d1e6474076366759db86f101778c5f20ccvboxsync}
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync/**
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Filter a the filename in the against a filter.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync *
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @returns true if the name matches the filter.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @returns false if the name doesn't match filter.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param pDir The directory handle.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param pszName The path to match to the filter.
de6e321f351aa489a6a62bed474390a0056e8093vboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsyncstatic DECLCALLBACK(bool) rtDirFilterWinNtMatchNoWildcards(PRTDIR pDir, const char *pszName)
de6e321f351aa489a6a62bed474390a0056e8093vboxsync{
de6e321f351aa489a6a62bed474390a0056e8093vboxsync /*
de6e321f351aa489a6a62bed474390a0056e8093vboxsync * Walk the string and compare.
de6e321f351aa489a6a62bed474390a0056e8093vboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync PCRTUNICP pucFilter = pDir->puszFilter;
044af0d1e6474076366759db86f101778c5f20ccvboxsync const char *psz = pszName;
044af0d1e6474076366759db86f101778c5f20ccvboxsync RTUNICP uc;
044af0d1e6474076366759db86f101778c5f20ccvboxsync do
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
de6e321f351aa489a6a62bed474390a0056e8093vboxsync int rc = RTStrGetCpEx(&psz, &uc);
044af0d1e6474076366759db86f101778c5f20ccvboxsync AssertRCReturn(rc, false);
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync RTUNICP ucFilter = *pucFilter++;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync if ( uc != ucFilter
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync && RTUniCpToUpper(uc) != ucFilter)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return false;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync } while (uc);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return true;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync}
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync/**
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Matches end of name.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsyncDECLINLINE(bool) rtDirFilterWinNtMatchEon(PCRTUNICP puszFilter)
044af0d1e6474076366759db86f101778c5f20ccvboxsync{
044af0d1e6474076366759db86f101778c5f20ccvboxsync RTUNICP ucFilter;
044af0d1e6474076366759db86f101778c5f20ccvboxsync while ( (ucFilter = *puszFilter) == '>'
044af0d1e6474076366759db86f101778c5f20ccvboxsync || ucFilter == '<'
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync || ucFilter == '*'
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync || ucFilter == '"')
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync puszFilter++;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return !ucFilter;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync}
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync/**
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Recursive star matching.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * Practically the same as normal star, except that the dos star stops
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * when hitting the last dot.
044af0d1e6474076366759db86f101778c5f20ccvboxsync *
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * @returns true on match.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * @returns false on miss.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsyncstatic bool rtDirFilterWinNtMatchDosStar(unsigned iDepth, RTUNICP uc, const char *pszNext, PCRTUNICP puszFilter)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync{
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync AssertReturn(iDepth++ < 256, false);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync /*
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * If there is no dos star, we should work just like the NT star.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Since that's generally faster algorithms, we jump down to there if we can.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync const char *pszDosDot = strrchr(pszNext, '.');
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (!pszDosDot && uc == '.')
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pszDosDot = pszNext - 1;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (!pszDosDot)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return rtDirFilterWinNtMatchStar(iDepth, uc, pszNext, puszFilter);
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Inspect the next filter char(s) until we find something to work on.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync RTUNICP ucFilter = *puszFilter++;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync switch (ucFilter)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /*
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * The star expression is the last in the pattern.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * We're fine if the name ends with a dot.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync case '\0':
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return !pszDosDot[1];
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /*
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Simplified by brute force.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync case '>': /* dos question mark */
044af0d1e6474076366759db86f101778c5f20ccvboxsync case '?':
044af0d1e6474076366759db86f101778c5f20ccvboxsync case '*':
044af0d1e6474076366759db86f101778c5f20ccvboxsync case '<': /* dos star */
044af0d1e6474076366759db86f101778c5f20ccvboxsync case '"': /* dos dot */
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync puszFilter--;
044af0d1e6474076366759db86f101778c5f20ccvboxsync const char *pszStart = pszNext;
044af0d1e6474076366759db86f101778c5f20ccvboxsync do
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter))
044af0d1e6474076366759db86f101778c5f20ccvboxsync return true;
044af0d1e6474076366759db86f101778c5f20ccvboxsync int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false);
044af0d1e6474076366759db86f101778c5f20ccvboxsync } while ((intptr_t)pszDosDot - (intptr_t)pszNext >= -1);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /* backtrack and do the current char. */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pszNext = RTStrPrevCp(NULL, pszStart); AssertReturn(pszNext, false);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Ok, we've got zero or more characters.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * We'll try match starting at each occurence of this character.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync default:
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync if ( RTUniCpToUpper(uc) == ucFilter
044af0d1e6474076366759db86f101778c5f20ccvboxsync && rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter))
044af0d1e6474076366759db86f101778c5f20ccvboxsync return true;
044af0d1e6474076366759db86f101778c5f20ccvboxsync do
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false);
044af0d1e6474076366759db86f101778c5f20ccvboxsync if ( RTUniCpToUpper(uc) == ucFilter
044af0d1e6474076366759db86f101778c5f20ccvboxsync && rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter))
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return true;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync } while ((intptr_t)pszDosDot - (intptr_t)pszNext >= -1);
044af0d1e6474076366759db86f101778c5f20ccvboxsync return false;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /* won't ever get here! */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync}
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync/**
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Recursive star matching.
72a6fe3989272cb2d409b50caca25e1edbca9398vboxsync *
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * @returns true on match.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * @returns false on miss.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsyncstatic bool rtDirFilterWinNtMatchStar(unsigned iDepth, RTUNICP uc, const char *pszNext, PCRTUNICP puszFilter)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync{
044af0d1e6474076366759db86f101778c5f20ccvboxsync AssertReturn(iDepth++ < 256, false);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /*
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Inspect the next filter char(s) until we find something to work on.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync for (;;)
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync RTUNICP ucFilter = *puszFilter++;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync switch (ucFilter)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /*
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * The star expression is the last in the pattern.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Cool, that means we're done!
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync case '\0':
044af0d1e6474076366759db86f101778c5f20ccvboxsync return true;
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Just in case (doubt we ever get here), just merge it with the current one.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync case '*':
044af0d1e6474076366759db86f101778c5f20ccvboxsync break;
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Skip a fixed number of chars.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Figure out how many by walking the filter ignoring '*'s.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync case '?':
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync unsigned cQms = 1;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync while ((ucFilter = *puszFilter) == '*' || ucFilter == '?')
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync cQms += ucFilter == '?';
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync puszFilter++;
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync }
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync do
de6e321f351aa489a6a62bed474390a0056e8093vboxsync {
2d8870843ff566fee9bd3a6a5942414254106479vboxsync if (!uc)
a1df400bbe9d64aad400442e56eb637019300a5evboxsync return false;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false);
044af0d1e6474076366759db86f101778c5f20ccvboxsync } while (--cQms > 0);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /* done? */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (!ucFilter)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return true;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync break;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /*
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * The simple way is to try char by char and match the remaining
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * expression. If it's trailing we're done.
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync case '>': /* dos question mark */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (rtDirFilterWinNtMatchEon(puszFilter))
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return true;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync const char *pszStart = pszNext;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync do
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter))
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return true;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false);
2d8870843ff566fee9bd3a6a5942414254106479vboxsync } while (uc);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /* backtrack and do the current char. */
044af0d1e6474076366759db86f101778c5f20ccvboxsync pszNext = RTStrPrevCp(NULL, pszStart); AssertReturn(pszNext, false);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
a1df400bbe9d64aad400442e56eb637019300a5evboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync /*
de6e321f351aa489a6a62bed474390a0056e8093vboxsync * This bugger is interesting.
de6e321f351aa489a6a62bed474390a0056e8093vboxsync * Time for brute force. Iterate the name char by char.
de6e321f351aa489a6a62bed474390a0056e8093vboxsync */
a1df400bbe9d64aad400442e56eb637019300a5evboxsync case '<':
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync do
a1df400bbe9d64aad400442e56eb637019300a5evboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (rtDirFilterWinNtMatchDosStar(iDepth, uc, pszNext, puszFilter))
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return true;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync } while (uc);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return false;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
a1df400bbe9d64aad400442e56eb637019300a5evboxsync * This guy matches a '.' or the end of the name.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * It's very simple if the rest of the filter expression also matches eon.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync case '"':
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (rtDirFilterWinNtMatchEon(puszFilter))
a1df400bbe9d64aad400442e56eb637019300a5evboxsync return true;
044af0d1e6474076366759db86f101778c5f20ccvboxsync ucFilter = '.';
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* fall thru */
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Ok, we've got zero or more characters.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * We'll try match starting at each occurence of this character.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync default:
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync do
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync if ( RTUniCpToUpper(uc) == ucFilter
044af0d1e6474076366759db86f101778c5f20ccvboxsync && rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter))
a1df400bbe9d64aad400442e56eb637019300a5evboxsync return true;
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false);
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync } while (uc);
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync return false;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync } /* for (;;) */
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* won't ever get here! */
044af0d1e6474076366759db86f101778c5f20ccvboxsync}
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync/**
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Filter a the filename in the against a filter.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync *
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * The rules are as follows:
044af0d1e6474076366759db86f101778c5f20ccvboxsync * '?' Matches exactly one char.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * '*' Matches zero or more chars.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * '<' The dos star, matches zero or more chars except the DOS dot.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * '>' The dos question mark, matches one char, but dots and end-of-name eats them.
7af218a7441de38fc9e814919db04bae3e917664vboxsync * '"' The dos dot, matches a dot or end-of-name.
7af218a7441de38fc9e814919db04bae3e917664vboxsync *
7af218a7441de38fc9e814919db04bae3e917664vboxsync * @returns true if the name matches the filter.
7af218a7441de38fc9e814919db04bae3e917664vboxsync * @returns false if the name doesn't match filter.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * @param iDepth The recursion depth.
7af218a7441de38fc9e814919db04bae3e917664vboxsync * @param pszName The path to match to the filter.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * @param puszFilter The filter string.
7af218a7441de38fc9e814919db04bae3e917664vboxsync */
7af218a7441de38fc9e814919db04bae3e917664vboxsyncstatic bool rtDirFilterWinNtMatchBase(unsigned iDepth, const char *pszName, PCRTUNICP puszFilter)
72a6fe3989272cb2d409b50caca25e1edbca9398vboxsync{
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync AssertReturn(iDepth++ < 256, false);
7af218a7441de38fc9e814919db04bae3e917664vboxsync
7af218a7441de38fc9e814919db04bae3e917664vboxsync /*
7af218a7441de38fc9e814919db04bae3e917664vboxsync * Walk the string and match it up char by char.
7af218a7441de38fc9e814919db04bae3e917664vboxsync */
7af218a7441de38fc9e814919db04bae3e917664vboxsync RTUNICP uc;
044af0d1e6474076366759db86f101778c5f20ccvboxsync do
7af218a7441de38fc9e814919db04bae3e917664vboxsync {
7af218a7441de38fc9e814919db04bae3e917664vboxsync RTUNICP ucFilter = *puszFilter++;
7af218a7441de38fc9e814919db04bae3e917664vboxsync int rc = RTStrGetCpEx(&pszName, &uc); AssertRCReturn(rc, false);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync switch (ucFilter)
72a6fe3989272cb2d409b50caca25e1edbca9398vboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* Exactly one char. */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync case '?':
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (!uc)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return false;
4e47bb772df0d04d1ded3e06354de547d52e2d06vboxsync break;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
7af218a7441de38fc9e814919db04bae3e917664vboxsync /* One char, but the dos dot and end-of-name eats '>' and '<'. */
7af218a7441de38fc9e814919db04bae3e917664vboxsync case '>': /* dos ? */
7af218a7441de38fc9e814919db04bae3e917664vboxsync if (!uc)
7af218a7441de38fc9e814919db04bae3e917664vboxsync return rtDirFilterWinNtMatchEon(puszFilter);
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (uc == '.')
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync while ((ucFilter = *puszFilter) == '>' || ucFilter == '<')
044af0d1e6474076366759db86f101778c5f20ccvboxsync puszFilter++;
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (ucFilter == '"' || ucFilter == '.') /* not 100% sure about the last dot */
77b92045ecae7978726dd23cb3d5de4676aec1c9vboxsync ++puszFilter;
044af0d1e6474076366759db86f101778c5f20ccvboxsync else /* the does question mark doesn't match '.'s, so backtrack. */
044af0d1e6474076366759db86f101778c5f20ccvboxsync pszName = RTStrPrevCp(NULL, pszName);
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync break;
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* Match a dot or the end-of-name. */
044af0d1e6474076366759db86f101778c5f20ccvboxsync case '"': /* dos '.' */
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (uc != '.')
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (uc)
044af0d1e6474076366759db86f101778c5f20ccvboxsync return false;
044af0d1e6474076366759db86f101778c5f20ccvboxsync return rtDirFilterWinNtMatchEon(puszFilter);
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync break;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /* zero or more */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync case '*':
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return rtDirFilterWinNtMatchStar(iDepth, uc, pszName, puszFilter);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync case '<': /* dos '*' */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return rtDirFilterWinNtMatchDosStar(iDepth, uc, pszName, puszFilter);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /* uppercased match */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync default:
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (RTUniCpToUpper(uc) != ucFilter)
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync return false;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync break;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync }
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync }
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync } while (uc);
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync return true;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync}
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync/**
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * Filter a the filename in the against a filter.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync *
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @returns true if the name matches the filter.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @returns false if the name doesn't match filter.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @param pDir The directory handle.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @param pszName The path to match to the filter.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync */
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsyncstatic DECLCALLBACK(bool) rtDirFilterWinNtMatch(PRTDIR pDir, const char *pszName)
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync{
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync return rtDirFilterWinNtMatchBase(0, pszName, pDir->puszFilter);
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync}
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync/**
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * Initializes a WinNt like wildcard filter.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync *
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @returns Pointer to the filter function.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @returns NULL if the filter doesn't filter out anything.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @param pDir The directory handle (not yet opened).
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync */
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsyncstatic PFNRTDIRFILTER rtDirFilterWinNtInit(PRTDIR pDir)
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync{
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync /*
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * Check for the usual * and <"< (*.* in DOS language) patterns.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync */
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync if ( (pDir->cchFilter == 1 && pDir->pszFilter[0] == '*')
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync || (pDir->cchFilter == 3 && !memcmp(pDir->pszFilter, "<\".>", 3))
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync )
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync return NULL;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync /*
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync * Uppercase the expression, also do a little optimizations when possible.
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync */
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync bool fHaveWildcards = false;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync unsigned iRead = 0;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync unsigned iWrite = 0;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync while (iRead < pDir->cucFilter)
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync {
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync RTUNICP uc = pDir->puszFilter[iRead++];
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync if (uc == '*')
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync {
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync fHaveWildcards = true;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync /* remove extra stars. */
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync RTUNICP uc2;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync while ((uc2 = pDir->puszFilter[iRead + 1]) == '*')
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync iRead++;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync }
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync else if (uc == '?' || uc == '>' || uc == '<' || uc == '"')
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync fHaveWildcards = true;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync else
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync uc = RTUniCpToUpper(uc);
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync pDir->puszFilter[iWrite++] = uc;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync }
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync pDir->puszFilter[iWrite] = 0;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync pDir->cucFilter = iWrite;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync return fHaveWildcards
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync ? rtDirFilterWinNtMatch
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync : rtDirFilterWinNtMatchNoWildcards;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync}
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync/**
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * Common worker for opening a directory.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync *
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @returns IPRT status code.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @param ppDir Where to store the directory handle.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @param pszPath The specified path.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @param pszFilter Pointer to where the filter start in the path. NULL if no filter.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * @param enmFilter The type of filter to apply.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync */
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsyncstatic int rtDirOpenCommon(PRTDIR *ppDir, const char *pszPath, const char *pszFilter, RTDIRFILTER enmFilter)
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync{
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync /*
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * Expand the path.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync *
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * The purpose of this exercise to have the abs path around
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * for querying extra information about the objects we list.
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync * As a sideeffect we also validate the path here.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync */
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync char szRealPath[RTPATH_MAX + 1];
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync int rc;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync size_t cbFilter; /* includes '\0' (thus cb and not cch). */
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync size_t cucFilter0; /* includes U+0. */
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync if (!pszFilter)
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync cbFilter = cucFilter0 = 0;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync rc = RTPathReal(pszPath, szRealPath, sizeof(szRealPath) - 1);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync else
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync cbFilter = strlen(pszFilter) + 1;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync cucFilter0 = RTStrUniLen(pszFilter) + 1;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (pszFilter != pszPath)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /* yea, I'm lazy. sue me. */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync char *pszTmp = RTStrDup(pszPath);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (!pszTmp)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return VERR_NO_MEMORY;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pszTmp[pszFilter - pszPath] = '\0';
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync rc = RTPathReal(pszTmp, szRealPath, sizeof(szRealPath) - 1);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync RTStrFree(pszTmp);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync else
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync rc = RTPathReal(".", szRealPath, sizeof(szRealPath) - 1);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (RT_FAILURE(rc))
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return rc;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /* add trailing '/' if missing. */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync size_t cchRealPath = strlen(szRealPath);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (!RTPATH_IS_SEP(szRealPath[cchRealPath - 1]))
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync szRealPath[cchRealPath++] = RTPATH_SLASH;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync szRealPath[cchRealPath] = '\0';
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /*
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Allocate and initialize the directory handle.
7af218a7441de38fc9e814919db04bae3e917664vboxsync *
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync * The posix definition of Data.d_name allows it to be < NAME_MAX + 1,
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync * thus the horrible uglyness here. Solaris uses d_name[1] for instance.
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync */
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync#ifndef RT_OS_WINDOWS
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync long cbNameMax = pathconf(szRealPath, _PC_NAME_MAX);
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync# ifdef NAME_MAX
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync if (cbNameMax < NAME_MAX) /* This is plain paranoia, but it doesn't hurt. */
9e47fe1a0782e9d50791ff47b79ca81c52855774vboxsync cbNameMax = NAME_MAX;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync# endif
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync# ifdef _XOPEN_NAME_MAX
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (cbNameMax < _XOPEN_NAME_MAX) /* Ditto. */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync cbNameMax = _XOPEN_NAME_MAX;
7af218a7441de38fc9e814919db04bae3e917664vboxsync# endif
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync size_t cbDir = RT_OFFSETOF(RTDIR, Data.d_name[cbNameMax + 1]);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (cbDir < sizeof(RTDIR)) /* Ditto. */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync cbDir = sizeof(RTDIR);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync cbDir = RT_ALIGN_Z(cbDir, 8);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync#else
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync size_t cbDir = sizeof(RTDIR);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync#endif
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync size_t const cbAllocated = cbDir
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync + cucFilter0 * sizeof(RTUNICP)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync + cbFilter
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync + cchRealPath + 1 + 4;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync PRTDIR pDir = (PRTDIR)RTMemAlloc(cbAllocated);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (!pDir)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return VERR_NO_MEMORY;
7af218a7441de38fc9e814919db04bae3e917664vboxsync uint8_t *pb = (uint8_t *)pDir + cbDir;
7af218a7441de38fc9e814919db04bae3e917664vboxsync
7af218a7441de38fc9e814919db04bae3e917664vboxsync /* initialize it */
7af218a7441de38fc9e814919db04bae3e917664vboxsync pDir->u32Magic = RTDIR_MAGIC;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (cbFilter)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync pDir->puszFilter = (PRTUNICP)pb;
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync rc = RTStrToUniEx(pszFilter, RTSTR_MAX, &pDir->puszFilter, cucFilter0, &pDir->cucFilter);
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync AssertRC(rc);
de6e321f351aa489a6a62bed474390a0056e8093vboxsync pb += cucFilter0 * sizeof(RTUNICP);
de6e321f351aa489a6a62bed474390a0056e8093vboxsync pDir->pszFilter = (char *)memcpy(pb, pszFilter, cbFilter);
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync pDir->cchFilter = cbFilter - 1;
044af0d1e6474076366759db86f101778c5f20ccvboxsync pb += cbFilter;
7af218a7441de38fc9e814919db04bae3e917664vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync else
de6e321f351aa489a6a62bed474390a0056e8093vboxsync {
4e47bb772df0d04d1ded3e06354de547d52e2d06vboxsync pDir->puszFilter = NULL;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync pDir->cucFilter = 0;
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync pDir->pszFilter = NULL;
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync pDir->cchFilter = 0;
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync }
de6e321f351aa489a6a62bed474390a0056e8093vboxsync pDir->enmFilter = enmFilter;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync switch (enmFilter)
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync default:
de6e321f351aa489a6a62bed474390a0056e8093vboxsync case RTDIRFILTER_NONE:
de6e321f351aa489a6a62bed474390a0056e8093vboxsync pDir->pfnFilter = NULL;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync break;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync case RTDIRFILTER_WINNT:
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pDir->pfnFilter = rtDirFilterWinNtInit(pDir);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync break;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync case RTDIRFILTER_UNIX:
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pDir->pfnFilter = NULL;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync break;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync case RTDIRFILTER_UNIX_UPCASED:
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pDir->pfnFilter = NULL;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync break;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pDir->cchPath = cchRealPath;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync pDir->pszPath = (char *)memcpy(pb, szRealPath, cchRealPath + 1);
de6e321f351aa489a6a62bed474390a0056e8093vboxsync Assert(pb - (uint8_t *)pDir + cchRealPath + 1 <= cbAllocated);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pDir->fDataUnread = false;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#ifndef RT_DONT_CONVERT_FILENAMES
de6e321f351aa489a6a62bed474390a0056e8093vboxsync pDir->pszName = NULL;
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync pDir->cchName = 0;
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync#endif
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync#ifndef RT_OS_WINDOWS
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync pDir->cbMaxName = cbDir - RT_OFFSETOF(RTDIR, Data.d_name);
de6e321f351aa489a6a62bed474390a0056e8093vboxsync#endif
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync /*
4e47bb772df0d04d1ded3e06354de547d52e2d06vboxsync * Hand it over to the native part.
de6e321f351aa489a6a62bed474390a0056e8093vboxsync */
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync rc = rtOpenDirNative(pDir, szRealPath);
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync if (RT_SUCCESS(rc))
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync *ppDir = pDir;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync else
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync RTMemFree(pDir);
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync return rc;
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync}
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync
172ae196da38208e5f1e3485715a89f2d53c6880vboxsyncRTDECL(int) RTDirOpen(PRTDIR *ppDir, const char *pszPath)
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync{
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /*
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync * Validate input.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync AssertMsgReturn(VALID_PTR(ppDir), ("%p\n", ppDir), VERR_INVALID_POINTER);
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync AssertMsgReturn(VALID_PTR(pszPath), ("%p\n", pszPath), VERR_INVALID_POINTER);
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * Take common cause with RTDirOpenFiltered().
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync int rc = rtDirOpenCommon(ppDir, pszPath, NULL, RTDIRFILTER_NONE);
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync LogFlow(("RTDirOpen(%p:{%p}, %p:{%s}): return %Rrc\n", ppDir, *ppDir, pszPath, pszPath, rc));
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync return rc;
044af0d1e6474076366759db86f101778c5f20ccvboxsync}
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsyncRTDECL(int) RTDirOpenFiltered(PRTDIR *ppDir, const char *pszPath, RTDIRFILTER enmFilter)
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync{
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * Validate input.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync */
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync AssertMsgReturn(VALID_PTR(ppDir), ("%p\n", ppDir), VERR_INVALID_POINTER);
de6e321f351aa489a6a62bed474390a0056e8093vboxsync AssertMsgReturn(VALID_PTR(pszPath), ("%p\n", pszPath), VERR_INVALID_POINTER);
de6e321f351aa489a6a62bed474390a0056e8093vboxsync switch (enmFilter)
de6e321f351aa489a6a62bed474390a0056e8093vboxsync {
20593760b116c90f3e439552763eef632a3bbb17vboxsync case RTDIRFILTER_UNIX:
de6e321f351aa489a6a62bed474390a0056e8093vboxsync case RTDIRFILTER_UNIX_UPCASED:
de6e321f351aa489a6a62bed474390a0056e8093vboxsync AssertMsgFailed(("%d is not implemented!\n", enmFilter));
de6e321f351aa489a6a62bed474390a0056e8093vboxsync return VERR_NOT_IMPLEMENTED;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync case RTDIRFILTER_NONE:
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync case RTDIRFILTER_WINNT:
de6e321f351aa489a6a62bed474390a0056e8093vboxsync break;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync default:
de6e321f351aa489a6a62bed474390a0056e8093vboxsync AssertMsgFailedReturn(("%d\n", enmFilter), VERR_INVALID_PARAMETER);
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync /*
de6e321f351aa489a6a62bed474390a0056e8093vboxsync * Find the last component, i.e. where the filter criteria starts and the dir name ends.
de6e321f351aa489a6a62bed474390a0056e8093vboxsync */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync const char *pszFilter = enmFilter != RTDIRFILTER_NONE
044af0d1e6474076366759db86f101778c5f20ccvboxsync ? RTPathFilename(pszPath)
044af0d1e6474076366759db86f101778c5f20ccvboxsync : NULL;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync /*
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * Call worker common with RTDirOpen which will verify the path, allocate
044af0d1e6474076366759db86f101778c5f20ccvboxsync * and initialize the handle, and finally call the backend.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
de6e321f351aa489a6a62bed474390a0056e8093vboxsync int rc = rtDirOpenCommon(ppDir, pszPath, pszFilter, enmFilter);
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync LogFlow(("RTDirOpenFiltered(%p:{%p}, %p:{%s}, %d): return %Rrc\n",
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ppDir, *ppDir, pszPath, pszPath, enmFilter, rc));
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return rc;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncRTDECL(int) RTDirRemoveRecursive(const char *pszPath)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync int rc;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (!RTDirExists(pszPath))
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return VINF_SUCCESS;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync char szAbsPath[RTPATH_MAX];
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** @todo use RTPathReal here instead? */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync rc = RTPathAbs(pszPath, szAbsPath, sizeof(szAbsPath));
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (RT_FAILURE(rc))
de6e321f351aa489a6a62bed474390a0056e8093vboxsync return rc;
de6e321f351aa489a6a62bed474390a0056e8093vboxsync
de6e321f351aa489a6a62bed474390a0056e8093vboxsync PRTDIR pDir = NULL;
rc = RTDirOpen(&pDir, szAbsPath);
if (RT_SUCCESS(rc))
{
RTDIRENTRY dirEntry;
size_t cbDirEntry = sizeof(dirEntry);
while ((rc = RTDirRead(pDir, &dirEntry, NULL /* Passing an argument won't work here yet. */)) == VINF_SUCCESS)
{
char* pszEntry = NULL;
rc = RTStrAPrintf(&pszEntry, "%s/%s", szAbsPath, dirEntry.szName);
if( RT_SUCCESS(rc)
&& strcmp(dirEntry.szName, ".")
&& strcmp(dirEntry.szName, ".."))
{
switch (dirEntry.enmType)
{
case RTDIRENTRYTYPE_FILE:
rc = RTFileDelete(pszEntry);
break;
case RTDIRENTRYTYPE_DIRECTORY:
rc = RTDirRemoveRecursive(pszEntry);
break;
default:
/** @todo not implemented yet. */
break;
}
RTStrFree(pszEntry);
}
if (RT_FAILURE(rc))
break;
}
if (rc == VERR_NO_MORE_FILES)
rc = VINF_SUCCESS;
RTDirClose(pDir);
rc = RTDirRemove(szAbsPath);
}
LogFlow(("RTDirRemoveRecursive(%p:{%s}): returns %Rrc\n", pszPath, pszPath, rc));
return rc;
}