diff options
Diffstat (limited to 'src/VBox/Runtime/common/path')
24 files changed, 1791 insertions, 116 deletions
diff --git a/src/VBox/Runtime/common/path/RTPathAbsDup.cpp b/src/VBox/Runtime/common/path/RTPathAbsDup.cpp index b9f217f9..337ce128 100644 --- a/src/VBox/Runtime/common/path/RTPathAbsDup.cpp +++ b/src/VBox/Runtime/common/path/RTPathAbsDup.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/RTPathAbsEx.cpp b/src/VBox/Runtime/common/path/RTPathAbsEx.cpp index c647b547..86ce86a0 100644 --- a/src/VBox/Runtime/common/path/RTPathAbsEx.cpp +++ b/src/VBox/Runtime/common/path/RTPathAbsEx.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/RTPathAbsExDup.cpp b/src/VBox/Runtime/common/path/RTPathAbsExDup.cpp index 8bb8cd17..9247d899 100644 --- a/src/VBox/Runtime/common/path/RTPathAbsExDup.cpp +++ b/src/VBox/Runtime/common/path/RTPathAbsExDup.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/RTPathAppend.cpp b/src/VBox/Runtime/common/path/RTPathAppend.cpp index 5bad6483..af3e5917 100644 --- a/src/VBox/Runtime/common/path/RTPathAppend.cpp +++ b/src/VBox/Runtime/common/path/RTPathAppend.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009 Oracle Corporation + * Copyright (C) 2009-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/RTPathAppendEx.cpp b/src/VBox/Runtime/common/path/RTPathAppendEx.cpp index e5de4ffe..ebed3864 100644 --- a/src/VBox/Runtime/common/path/RTPathAppendEx.cpp +++ b/src/VBox/Runtime/common/path/RTPathAppendEx.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009-2010 Oracle Corporation + * Copyright (C) 2009-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/RTPathCalcRelative.cpp b/src/VBox/Runtime/common/path/RTPathCalcRelative.cpp new file mode 100644 index 00000000..fbb6b64c --- /dev/null +++ b/src/VBox/Runtime/common/path/RTPathCalcRelative.cpp @@ -0,0 +1,130 @@ +/* $Id: RTPathCalcRelative.cpp $ */ +/** @file + * IPRT - RTPathCreateRelative. + */ + +/* + * Copyright (C) 2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include "internal/iprt.h" +#include <iprt/path.h> +#include <iprt/assert.h> +#include <iprt/err.h> +#include <iprt/string.h> +#include "internal/path.h" + + + +RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst, + const char *pszPathFrom, + const char *pszPathTo) +{ + int rc = VINF_SUCCESS; + + AssertPtrReturn(pszPathDst, VERR_INVALID_POINTER); + AssertReturn(cbPathDst, VERR_INVALID_PARAMETER); + AssertPtrReturn(pszPathFrom, VERR_INVALID_POINTER); + AssertPtrReturn(pszPathTo, VERR_INVALID_POINTER); + AssertReturn(RTPathStartsWithRoot(pszPathFrom), VERR_INVALID_PARAMETER); + AssertReturn(RTPathStartsWithRoot(pszPathTo), VERR_INVALID_PARAMETER); + AssertReturn(RTStrCmp(pszPathFrom, pszPathTo), VERR_INVALID_PARAMETER); + + /* + * Check for different root specifiers (drive letters), creating a relative path doesn't work here. + * @todo: How to handle case insensitive root specifiers correctly? + */ + size_t offRootFrom = rtPathRootSpecLen(pszPathFrom); + size_t offRootTo = rtPathRootSpecLen(pszPathTo); + + if ( offRootFrom != offRootTo + || RTStrNCmp(pszPathFrom, pszPathTo, offRootFrom)) + return VERR_NOT_SUPPORTED; + + /* Filter out the parent path which is equal to both paths. */ + while ( *pszPathFrom == *pszPathTo + && *pszPathFrom != '\0' + && *pszPathTo != '\0') + { + pszPathFrom++; + pszPathTo++; + } + + /* + * Because path components can start with an equal string but differ afterwards we + * need to go back to the beginning of the current component. + */ + while (!RTPATH_IS_SEP(*pszPathFrom)) + pszPathFrom--; + + pszPathFrom++; /* Skip path separator. */ + + while (!RTPATH_IS_SEP(*pszPathTo)) + pszPathTo--; + + pszPathTo++; /* Skip path separator. */ + + /* Paths point to the first non equal component now. */ + char aszPathTmp[RTPATH_MAX + 1]; + unsigned offPathTmp = 0; + + /* Create the part to go up from pszPathFrom. */ + while (*pszPathFrom != '\0') + { + while ( !RTPATH_IS_SEP(*pszPathFrom) + && *pszPathFrom != '\0') + pszPathFrom++; + + if (RTPATH_IS_SEP(*pszPathFrom)) + { + if (offPathTmp + 3 >= sizeof(aszPathTmp) - 1) + return VERR_FILENAME_TOO_LONG; + aszPathTmp[offPathTmp++] = '.'; + aszPathTmp[offPathTmp++] = '.'; + aszPathTmp[offPathTmp++] = RTPATH_SLASH; + pszPathFrom++; + } + } + + aszPathTmp[offPathTmp] = '\0'; + + /* Now append the rest of pszPathTo to the final path. */ + char *pszPathTmp = &aszPathTmp[offPathTmp]; + size_t cbPathTmp = sizeof(aszPathTmp) - offPathTmp - 1; + rc = RTStrCatP(&pszPathTmp, &cbPathTmp, pszPathTo); + if (RT_SUCCESS(rc)) + { + *pszPathTmp = '\0'; + + size_t cchPathTmp = strlen(aszPathTmp); + if (cchPathTmp >= cbPathDst) + return VERR_BUFFER_OVERFLOW; + memcpy(pszPathDst, aszPathTmp, cchPathTmp + 1); + } + else + rc = VERR_FILENAME_TOO_LONG; + + return rc; +} + diff --git a/src/VBox/Runtime/common/path/RTPathExt.cpp b/src/VBox/Runtime/common/path/RTPathExt.cpp index 292c5f2f..bb2ee52e 100644 --- a/src/VBox/Runtime/common/path/RTPathExt.cpp +++ b/src/VBox/Runtime/common/path/RTPathExt.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/RTPathFilename.cpp b/src/VBox/Runtime/common/path/RTPathFilename.cpp index 2eeaba5e..3278383d 100644 --- a/src/VBox/Runtime/common/path/RTPathFilename.cpp +++ b/src/VBox/Runtime/common/path/RTPathFilename.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -30,46 +30,70 @@ *******************************************************************************/ #include "internal/iprt.h" #include <iprt/path.h> -#include <iprt/string.h> + +#include <iprt/assert.h> -/** - * Finds the filename in a path. - * - * @returns Pointer to filename within pszPath. - * @returns NULL if no filename (i.e. empty string or ends with a slash). - * @param pszPath Path to find filename in. - */ RTDECL(char *) RTPathFilename(const char *pszPath) { + return RTPathFilenameEx(pszPath, RTPATH_STYLE); +} +RT_EXPORT_SYMBOL(RTPathFilename); + + +RTDECL(char *) RTPathFilenameEx(const char *pszPath, uint32_t fFlags) +{ const char *psz = pszPath; const char *pszName = pszPath; - for (;; psz++) + Assert(RTPATH_STR_F_IS_VALID(fFlags, 0 /*no extra flags*/)); + fFlags &= RTPATH_STR_F_STYLE_MASK; + if (fFlags == RTPATH_STR_F_STYLE_HOST) + fFlags = RTPATH_STYLE; + if (fFlags == RTPATH_STR_F_STYLE_DOS) { - switch (*psz) + for (;; psz++) { - /* handle separators. */ -#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) - case ':': - pszName = psz + 1; - break; + switch (*psz) + { + /* handle separators. */ + case ':': + case '\\': + case '/': + pszName = psz + 1; + break; - case '\\': -#endif - case '/': - pszName = psz + 1; - break; + /* the end */ + case '\0': + if (*pszName) + return (char *)(void *)pszName; + return NULL; + } + } + } + else + { + Assert(fFlags == RTPATH_STR_F_STYLE_UNIX); + for (;; psz++) + { + switch (*psz) + { + /* handle separators. */ + case '/': + pszName = psz + 1; + break; - /* the end */ - case '\0': - if (*pszName) - return (char *)(void *)pszName; - return NULL; + /* the end */ + case '\0': + if (*pszName) + return (char *)(void *)pszName; + return NULL; + } } } /* not reached */ } +RT_EXPORT_SYMBOL(RTPathFilenameEx); diff --git a/src/VBox/Runtime/common/path/RTPathParse.cpp b/src/VBox/Runtime/common/path/RTPathParse.cpp index ce42e330..3ead6908 100644 --- a/src/VBox/Runtime/common/path/RTPathParse.cpp +++ b/src/VBox/Runtime/common/path/RTPathParse.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -31,88 +31,45 @@ #include "internal/iprt.h" #include <iprt/path.h> +#include <iprt/assert.h> +#include <iprt/ctype.h> +#include <iprt/err.h> +#include <iprt/string.h> -/** - * Parses a path. - * - * It figures the length of the directory component, the offset of - * the file name and the location of the suffix dot. - * - * @returns The path length. - * - * @param pszPath Path to find filename in. - * @param pcchDir Where to put the length of the directory component. If - * no directory, this will be 0. Optional. - * @param poffName Where to store the filename offset. - * If empty string or if it's ending with a slash this - * will be set to -1. Optional. - * @param poffSuff Where to store the suffix offset (the last dot). - * If empty string or if it's ending with a slash this - * will be set to -1. Optional. - */ -RTDECL(size_t) RTPathParse(const char *pszPath, size_t *pcchDir, ssize_t *poffName, ssize_t *poffSuff) +#define RTPATH_TEMPLATE_CPP_H "RTPathParse.cpp.h" +#include "rtpath-expand-template.cpp.h" + + +RTDECL(int) RTPathParse(const char *pszPath, PRTPATHPARSED pParsed, size_t cbParsed, uint32_t fFlags) { - const char *psz = pszPath; - ssize_t offRoot = 0; - const char *pszName = pszPath; - const char *pszLastDot = NULL; + /* + * Input validation. + */ + AssertReturn(cbParsed >= RT_UOFFSETOF(RTPATHPARSED, aComps), VERR_INVALID_PARAMETER); + AssertPtrReturn(pParsed, VERR_INVALID_POINTER); + AssertPtrReturn(pszPath, VERR_INVALID_POINTER); + AssertReturn(*pszPath, VERR_PATH_ZERO_LENGTH); + AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, 0), VERR_INVALID_FLAGS); - for (;; psz++) + /* + * Invoke the worker for the selected path style. + */ + switch (fFlags & RTPATH_STR_F_STYLE_MASK) { - switch (*psz) - { - /* handle separators. */ -#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) - case ':': - pszName = psz + 1; - offRoot = pszName - psz; - break; - - case '\\': +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) + case RTPATH_STR_F_STYLE_HOST: #endif - case '/': - pszName = psz + 1; - break; - - case '.': - pszLastDot = psz; - break; - - /* - * The end. Complete the results. - */ - case '\0': - { - ssize_t offName = *pszName != '\0' ? pszName - pszPath : -1; - if (poffName) - *poffName = offName; + case RTPATH_STR_F_STYLE_DOS: + return rtPathParseStyleDos(pszPath, pParsed, cbParsed, fFlags); - if (poffSuff) - { - ssize_t offSuff = -1; - if (pszLastDot) - { - offSuff = pszLastDot - pszPath; - if (offSuff <= offName) - offSuff = -1; - } - *poffSuff = offSuff; - } - - if (pcchDir) - { - ssize_t off = offName - 1; - while (off >= offRoot && RTPATH_IS_SLASH(pszPath[off])) - off--; - *pcchDir = RT_MAX(off, offRoot) + 1; - } +#if !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) + case RTPATH_STR_F_STYLE_HOST: +#endif + case RTPATH_STR_F_STYLE_UNIX: + return rtPathParseStyleUnix(pszPath, pParsed, cbParsed, fFlags); - return psz - pszPath; - } - } + default: + AssertFailedReturn(VERR_INVALID_FLAGS); /* impossible */ } - - /* will never get here */ - return 0; } diff --git a/src/VBox/Runtime/common/path/RTPathParse.cpp.h b/src/VBox/Runtime/common/path/RTPathParse.cpp.h new file mode 100644 index 00000000..bef8e7a1 --- /dev/null +++ b/src/VBox/Runtime/common/path/RTPathParse.cpp.h @@ -0,0 +1,250 @@ +/* $Id: RTPathParse.cpp.h $ */ +/** @file + * IPRT - RTPathParse - Code Template. + * + * This file included multiple times with different path style macros. + */ + +/* + * Copyright (C) 2006-2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + + +/** + * @copydoc RTPathParse + */ +static int RTPATH_STYLE_FN(rtPathParse)(const char *pszPath, PRTPATHPARSED pParsed, size_t cbParsed, uint32_t fFlags) +{ + /* + * Parse the root specification if present and initialize the parser state + * (keep it on the stack for speed). + */ + uint32_t const cMaxComps = cbParsed < RT_UOFFSETOF(RTPATHPARSED, aComps[0xfff0]) + ? (uint32_t)((cbParsed - RT_UOFFSETOF(RTPATHPARSED, aComps)) / sizeof(pParsed->aComps[0])) + : 0xfff0; + uint32_t idxComp = 0; + uint32_t cchPath; + uint32_t offCur; + uint16_t fProps; + + if (RTPATH_IS_SLASH(pszPath[0])) + { + if (fFlags & RTPATH_STR_F_NO_START) + { + offCur = 1; + while (RTPATH_IS_SLASH(pszPath[offCur])) + offCur++; + if (!pszPath[offCur]) + return VERR_PATH_ZERO_LENGTH; + fProps = RTPATH_PROP_RELATIVE | RTPATH_PROP_EXTRA_SLASHES; + cchPath = 0; + } +#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS + else if ( RTPATH_IS_SLASH(pszPath[1]) + && !RTPATH_IS_SLASH(pszPath[2]) + && pszPath[2]) + { + /* UNC - skip to the end of the potential namespace or computer name. */ + offCur = 2; + while (!RTPATH_IS_SLASH(pszPath[offCur]) && pszPath[offCur]) + offCur++; + + /* If there is another slash, we considered it a valid UNC path, if + not it's just a root path with an extra slash thrown in. */ + if (RTPATH_IS_SLASH(pszPath[offCur])) + { + fProps = RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_UNC | RTPATH_PROP_ABSOLUTE; + offCur++; + cchPath = offCur; + } + else + { + fProps = RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE; + offCur = 1; + cchPath = 1; + } + } +#endif + else + { +#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS + fProps = RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE; +#else + fProps = RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE; +#endif + offCur = 1; + cchPath = 1; + } + } +#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS + else if (RT_C_IS_ALPHA(pszPath[0]) && pszPath[1] == ':') + { + if (!RTPATH_IS_SLASH(pszPath[2])) + { + fProps = RTPATH_PROP_VOLUME | RTPATH_PROP_RELATIVE; + offCur = 2; + } + else + { + fProps = RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE; + offCur = 3; + } + cchPath = offCur; + } +#endif + else + { + fProps = RTPATH_PROP_RELATIVE; + offCur = 0; + cchPath = 0; + } + + /* Add it to the component array . */ + if (offCur && !(fFlags & RTPATH_STR_F_NO_START)) + { + cchPath = offCur; + if (idxComp < cMaxComps) + { + pParsed->aComps[idxComp].off = 0; + pParsed->aComps[idxComp].cch = offCur; + } + idxComp++; + + /* Skip unnecessary slashes following the root-spec. */ + if (RTPATH_IS_SLASH(pszPath[offCur])) + { + fProps |= RTPATH_PROP_EXTRA_SLASHES; + do + offCur++; + while (RTPATH_IS_SLASH(pszPath[offCur])); + } + } + + /* + * Parse the rest. + */ + if (pszPath[offCur]) + { + for (;;) + { + Assert(!RTPATH_IS_SLASH(pszPath[offCur])); + + /* Find the end of the component. */ + uint32_t offStart = offCur; + char ch; + while ((ch = pszPath[offCur]) != '\0' && !RTPATH_IS_SLASH(ch)) + offCur++; + if (offCur >= _64K) + return VERR_FILENAME_TOO_LONG; + + /* Add it. */ + uint32_t cchComp = offCur - offStart; + if (idxComp < cMaxComps) + { + pParsed->aComps[idxComp].off = offStart; + pParsed->aComps[idxComp].cch = cchComp; + } + idxComp++; + cchPath += cchComp; + + /* Look for '.' and '..' references. */ + if (cchComp == 1 && pszPath[offCur - 1] == '.') + fProps |= RTPATH_PROP_DOT_REFS; + else if (cchComp == 2 && pszPath[offCur - 1] == '.' && pszPath[offCur - 2] == '.') + { + fProps &= ~RTPATH_PROP_ABSOLUTE; + fProps |= RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_RELATIVE; + } + + /* Skip unnecessary slashes. Leave ch unchanged! */ + char ch2 = ch; + if (ch2) + { + ch2 = pszPath[++offCur]; + if (RTPATH_IS_SLASH(ch2)) + { + fProps |= RTPATH_PROP_EXTRA_SLASHES; + do + ch2 = pszPath[++offCur]; + while (RTPATH_IS_SLASH(ch2)); + } + } + + /* The end? */ + if (ch2 == '\0') + { + pParsed->offSuffix = offCur; + pParsed->cchSuffix = 0; + if (ch) + { + if (!(fFlags & RTPATH_STR_F_NO_END)) + { + fProps |= RTPATH_PROP_DIR_SLASH; /* (not counted in component, but in cchPath) */ + cchPath++; + } + else + fProps |= RTPATH_PROP_EXTRA_SLASHES; + } + else if (!(fFlags & RTPATH_STR_F_NO_END)) + { + fProps |= RTPATH_PROP_FILENAME; + + /* look for an ? */ + uint16_t cDots = 0; + uint32_t offSuffix = offStart + cchComp; + while (offSuffix-- > offStart) + if (pszPath[offSuffix] == '.') + { + uint32_t cchSuffix = offStart + cchComp - offSuffix; + if (cchSuffix > 1 && offStart != offSuffix) + { + pParsed->cchSuffix = cchSuffix; + pParsed->offSuffix = offSuffix; + fProps |= RTPATH_PROP_SUFFIX; + } + break; + } + } + break; + } + + /* No, not the end. Account for an separator before we restart the loop. */ + cchPath += sizeof(RTPATH_SLASH_STR) - 1; + } + } + else + { + pParsed->offSuffix = offCur; + pParsed->cchSuffix = 0; + } + if (offCur >= _64K) + return VERR_FILENAME_TOO_LONG; + + /* + * Store the remainder of the state and we're done. + */ + pParsed->fProps = fProps; + pParsed->cchPath = cchPath; + pParsed->cComps = idxComp; + + return idxComp <= cMaxComps ? VINF_SUCCESS : VERR_BUFFER_OVERFLOW; +} + diff --git a/src/VBox/Runtime/common/path/RTPathParseSimple.cpp b/src/VBox/Runtime/common/path/RTPathParseSimple.cpp new file mode 100644 index 00000000..f6de9aa2 --- /dev/null +++ b/src/VBox/Runtime/common/path/RTPathParseSimple.cpp @@ -0,0 +1,118 @@ +/* $Id: RTPathParseSimple.cpp $ */ +/** @file + * IPRT - RTPathParseSimple + */ + +/* + * Copyright (C) 2006-2012 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include "internal/iprt.h" +#include <iprt/path.h> + + +/** + * Parses a path. + * + * It figures the length of the directory component, the offset of + * the file name and the location of the suffix dot. + * + * @returns The path length. + * + * @param pszPath Path to find filename in. + * @param pcchDir Where to put the length of the directory component. If + * no directory, this will be 0. Optional. + * @param poffName Where to store the filename offset. + * If empty string or if it's ending with a slash this + * will be set to -1. Optional. + * @param poffSuff Where to store the suffix offset (the last dot). + * If empty string or if it's ending with a slash this + * will be set to -1. Optional. + */ +RTDECL(size_t) RTPathParseSimple(const char *pszPath, size_t *pcchDir, ssize_t *poffName, ssize_t *poffSuff) +{ + const char *psz = pszPath; + ssize_t offRoot = 0; + const char *pszName = pszPath; + const char *pszLastDot = NULL; + + for (;; psz++) + { + switch (*psz) + { + /* handle separators. */ +#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) + case ':': + pszName = psz + 1; + offRoot = pszName - psz; + break; + + case '\\': +#endif + case '/': + pszName = psz + 1; + break; + + case '.': + pszLastDot = psz; + break; + + /* + * The end. Complete the results. + */ + case '\0': + { + ssize_t offName = *pszName != '\0' ? pszName - pszPath : -1; + if (poffName) + *poffName = offName; + + if (poffSuff) + { + ssize_t offSuff = -1; + if (pszLastDot) + { + offSuff = pszLastDot - pszPath; + if (offSuff <= offName) + offSuff = -1; + } + *poffSuff = offSuff; + } + + if (pcchDir) + { + ssize_t off = offName - 1; + while (off >= offRoot && RTPATH_IS_SLASH(pszPath[off])) + off--; + *pcchDir = RT_MAX(off, offRoot) + 1; + } + + return psz - pszPath; + } + } + } + + /* will never get here */ + return 0; +} + diff --git a/src/VBox/Runtime/common/path/RTPathParsedReassemble.cpp b/src/VBox/Runtime/common/path/RTPathParsedReassemble.cpp new file mode 100644 index 00000000..5ba842c0 --- /dev/null +++ b/src/VBox/Runtime/common/path/RTPathParsedReassemble.cpp @@ -0,0 +1,122 @@ +/* $Id: RTPathParsedReassemble.cpp $ */ +/** @file + * IPRT - RTPathParsedReassemble. + */ + +/* + * Copyright (C) 2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include "internal/iprt.h" +#include <iprt/path.h> + +#include <iprt/assert.h> +#include <iprt/err.h> +#include <iprt/string.h> + + +RTDECL(int) RTPathParsedReassemble(const char *pszSrcPath, PRTPATHPARSED pParsed, uint32_t fFlags, + char *pszDstPath, size_t cbDstPath) +{ + /* + * Input validation. + */ + AssertPtrReturn(pszSrcPath, VERR_INVALID_POINTER); + AssertPtrReturn(pParsed, VERR_INVALID_POINTER); + AssertReturn(pParsed->cComps > 0, VERR_INVALID_PARAMETER); + AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, 0) && !(fFlags & RTPATH_STR_F_MIDDLE), VERR_INVALID_FLAGS); + AssertPtrReturn(pszDstPath, VERR_INVALID_POINTER); + AssertReturn(cbDstPath > pParsed->cchPath, VERR_BUFFER_OVERFLOW); + + /* + * Figure which slash to use. + */ + char chSlash; + switch (fFlags & RTPATH_STR_F_STYLE_MASK) + { + case RTPATH_STR_F_STYLE_HOST: + chSlash = RTPATH_SLASH; + break; + + case RTPATH_STR_F_STYLE_DOS: + chSlash = '\\'; + break; + + case RTPATH_STR_F_STYLE_UNIX: + chSlash = '/'; + break; + + default: + AssertFailedReturn(VERR_INVALID_FLAGS); /* impossible */ + } + + /* + * Do the joining. + */ + uint32_t const cchOrgPath = pParsed->cchPath; + uint32_t cchDstPath = 0; + uint32_t const cComps = pParsed->cComps; + uint32_t idxComp = 0; + char *pszDst = pszDstPath; + uint32_t cchComp; + + if (RTPATH_PROP_HAS_ROOT_SPEC(pParsed->fProps)) + { + cchComp = pParsed->aComps[0].cch; + cchDstPath += cchComp; + AssertReturn(cchDstPath <= cchOrgPath, VERR_INVALID_PARAMETER); + memcpy(pszDst, &pszSrcPath[pParsed->aComps[0].off], cchComp); + + /* fix the slashes */ + char chOtherSlash = chSlash == '\\' ? '/' : '\\'; + while (cchComp-- > 0) + { + if (*pszDst == chOtherSlash) + *pszDst = chSlash; + pszDst++; + } + idxComp = 1; + } + + while (idxComp < cComps) + { + cchComp = pParsed->aComps[idxComp].cch; + cchDstPath += cchComp; + AssertReturn(cchDstPath <= cchOrgPath, VERR_INVALID_PARAMETER); + memcpy(pszDst, &pszSrcPath[pParsed->aComps[idxComp].off], cchComp); + pszDst += cchComp; + idxComp++; + if (idxComp != cComps || (pParsed->fProps & RTPATH_PROP_DIR_SLASH)) + { + cchDstPath++; + AssertReturn(cchDstPath <= cchOrgPath, VERR_INVALID_PARAMETER); + *pszDst++ = chSlash; + } + } + + *pszDst = '\0'; + + return VINF_SUCCESS; +} + diff --git a/src/VBox/Runtime/common/path/RTPathRealDup.cpp b/src/VBox/Runtime/common/path/RTPathRealDup.cpp index 18ce0a82..c0d84e40 100644 --- a/src/VBox/Runtime/common/path/RTPathRealDup.cpp +++ b/src/VBox/Runtime/common/path/RTPathRealDup.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/RTPathRmCmd.cpp b/src/VBox/Runtime/common/path/RTPathRmCmd.cpp new file mode 100644 index 00000000..cfb9b73b --- /dev/null +++ b/src/VBox/Runtime/common/path/RTPathRmCmd.cpp @@ -0,0 +1,648 @@ +/* $Id: RTPathRmCmd.cpp $ */ +/** @file + * IPRT - TAR Command. + */ + +/* + * Copyright (C) 2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include <iprt/path.h> + +#include <iprt/buildconfig.h> +#include <iprt/ctype.h> +#include <iprt/file.h> +#include <iprt/dir.h> +#include <iprt/getopt.h> +#include <iprt/initterm.h> +#include <iprt/message.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/symlink.h> + + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +#define RTPATHRMCMD_OPT_INTERACTIVE 1000 +#define RTPATHRMCMD_OPT_ONE_FILE_SYSTEM 1001 +#define RTPATHRMCMD_OPT_PRESERVE_ROOT 1002 +#define RTPATHRMCMD_OPT_NO_PRESERVE_ROOT 1003 +#define RTPATHRMCMD_OPT_MACHINE_READABLE 1004 + +/** The max directory entry size. */ +#define RTPATHRM_DIR_MAX_ENTRY_SIZE (sizeof(RTDIRENTRYEX) + 4096) + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** Interactive option. */ +typedef enum +{ + RTPATHRMCMDINTERACTIVE_NONE = 1, + RTPATHRMCMDINTERACTIVE_ALL, + RTPATHRMCMDINTERACTIVE_ONCE + /** @todo possible that we should by default prompt if removing read-only + * files or files owned by someone else. We currently don't. */ +} RTPATHRMCMDINTERACTIVE; + +/** + * IPRT rm option structure. + */ +typedef struct RTPATHRMCMDOPTS +{ + /** Whether to delete recursively. */ + bool fRecursive; + /** Whether to delete directories as well as other kinds of files. */ + bool fDirsAndOther; + /** Whether to remove files without prompting and ignoring non-existing + * files. */ + bool fForce; + /** Machine readable output. */ + bool fMachineReadable; + /** Don't try remove root ('/') if set, otherwise don't treat root specially. */ + bool fPreserveRoot; + /** Whether to keep to one file system. */ + bool fOneFileSystem; + /** Whether to safely delete files (overwrite 3x before unlinking). */ + bool fSafeDelete; + /** Whether to be verbose about the operation. */ + bool fVerbose; + /** The interactive setting. */ + RTPATHRMCMDINTERACTIVE enmInteractive; +} RTPATHRMCMDOPTS; +/** Pointer to the IPRT rm options. */ +typedef RTPATHRMCMDOPTS *PRTPATHRMCMDOPTS; + + +/******************************************************************************* +* Global Variables * +*******************************************************************************/ +/** A bunch of zeros. */ +static uint8_t const g_abZeros[16384] = { 0 }; +/** A bunch of 0xFF bytes. (lazy init) */ +static uint8_t g_ab0xFF[16384]; + + +static void rtPathRmVerbose(PRTPATHRMCMDOPTS pOpts, const char *pszPath) +{ + if (!pOpts->fMachineReadable) + RTPrintf("%s\n", pszPath); +} + + +static int rtPathRmError(PRTPATHRMCMDOPTS pOpts, const char *pszPath, int rc, + const char *pszFormat, ...) +{ + if (pOpts->fMachineReadable) + RTPrintf("fname=%s%crc=%d%c", pszPath, rc); + else + { + va_list va; + va_start(va, pszFormat); + RTMsgErrorV(pszFormat, va); + va_end(va); + } + return rc; +} + + +/** + * Worker that removes a symbolic link. + * + * @returns IPRT status code, errors go via rtPathRmError. + * @param pOpts The RM options. + * @param pszPath The path to the symbolic link. + */ +static int rtPathRmOneSymlink(PRTPATHRMCMDOPTS pOpts, const char *pszPath) +{ + if (pOpts->fVerbose) + rtPathRmVerbose(pOpts, pszPath); + int rc = RTSymlinkDelete(pszPath, 0); + if (RT_FAILURE(rc)) + return rtPathRmError(pOpts, pszPath, rc, "Error removing symbolic link '%s': %Rrc\n", pszPath, rc); + return rc; +} + + +/** + * Worker that removes a file. + * + * Currently used to delete both regular and special files. + * + * @returns IPRT status code, errors go via rtPathRmError. + * @param pOpts The RM options. + * @param pszPath The path to the file. + * @param pObjInfo The FS object info for the file. + */ +static int rtPathRmOneFile(PRTPATHRMCMDOPTS pOpts, const char *pszPath, PRTFSOBJINFO pObjInfo) +{ + int rc; + if (pOpts->fVerbose) + rtPathRmVerbose(pOpts, pszPath); + + /* + * Wipe the file if requested and possible. + */ + if (pOpts->fSafeDelete && RTFS_IS_FILE(pObjInfo->Attr.fMode)) + { + /* Lazy init of the 0xff buffer. */ + if (g_ab0xFF[0] != 0xff || g_ab0xFF[sizeof(g_ab0xFF) - 1] != 0xff) + memset(g_ab0xFF, 0xff, sizeof(g_ab0xFF)); + + RTFILE hFile; + rc = RTFileOpen(&hFile, pszPath, RTFILE_O_WRITE); + if (RT_FAILURE(rc)) + return rtPathRmError(pOpts, pszPath, rc, "Opening '%s' for overwriting: %Rrc\n", pszPath, rc); + + for (unsigned iPass = 0; iPass < 3; iPass++) + { + uint8_t const *pabFiller = iPass == 1 ? g_abZeros : g_ab0xFF; + size_t const cbFiller = iPass == 1 ? sizeof(g_abZeros) : sizeof(g_ab0xFF); + + rc = RTFileSeek(hFile, 0, RTFILE_SEEK_BEGIN, NULL); + if (RT_FAILURE(rc)) + { + rc = rtPathRmError(pOpts, pszPath, rc, "Error seeking to start of '%s': %Rrc\n", pszPath, rc); + break; + } + for (RTFOFF cbLeft = pObjInfo->cbObject; cbLeft > 0; cbLeft -= cbFiller) + { + size_t cbToWrite = cbFiller; + if (cbLeft < (RTFOFF)cbToWrite) + cbToWrite = (size_t)cbLeft; + rc = RTFileWrite(hFile, pabFiller, cbToWrite, NULL); + if (RT_FAILURE(rc)) + { + rc = rtPathRmError(pOpts, pszPath, rc, "Error writing to '%s': %Rrc\n", pszPath, rc); + break; + } + } + } + + int rc2 = RTFileClose(hFile); + if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) + return rtPathRmError(pOpts, pszPath, rc2, "Closing '%s' failed: %Rrc\n", pszPath, rc); + if (RT_FAILURE(rc)) + return rc; + } + + /* + * Remove the file. + */ + rc = RTFileDelete(pszPath); + if (RT_FAILURE(rc)) + return rtPathRmError(pOpts, pszPath, rc, + RTFS_IS_FILE(pObjInfo->Attr.fMode) + ? "Error removing regular file '%s': %Rrc\n" + : "Error removing special file '%s': %Rrc\n", + pszPath, rc); + return rc; +} + + +/** + * Deletes one directory (if it's empty). + * + * @returns IPRT status code, errors go via rtPathRmError. + * @param pOpts The RM options. + * @param pszPath The path to the directory. + */ +static int rtPathRmOneDir(PRTPATHRMCMDOPTS pOpts, const char *pszPath) +{ + if (pOpts->fVerbose) + rtPathRmVerbose(pOpts, pszPath); + + int rc = RTDirRemove(pszPath); + if (RT_FAILURE(rc)) + return rtPathRmError(pOpts, pszPath, rc, "Error removing directory '%s': %Rrc", pszPath, rc); + return rc; +} + + +/** + * Recursively delete a directory. + * + * @returns IPRT status code, errors go via rtPathRmError. + * @param pOpts The RM options. + * @param pszPath Pointer to a writable buffer holding the path to + * the directory. + * @param cchPath The length of the path (avoid strlen). + * @param pDirEntry Pointer to a directory entry buffer that is + * RTPATHRM_DIR_MAX_ENTRY_SIZE bytes big. + */ +static int rtPathRmRecursive(PRTPATHRMCMDOPTS pOpts, char *pszPath, size_t cchPath, PRTDIRENTRYEX pDirEntry) +{ + /* + * Make sure the path ends with a slash. + */ + if (!cchPath || !RTPATH_IS_SLASH(pszPath[cchPath - 1])) + { + if (cchPath + 1 >= RTPATH_MAX) + return rtPathRmError(pOpts, pszPath, VERR_BUFFER_OVERFLOW, "Buffer overflow fixing up '%s'.\n", pszPath); + pszPath[cchPath++] = RTPATH_SLASH; + pszPath[cchPath] = '\0'; + } + + /* + * Traverse the directory. + */ + PRTDIR hDir; + int rc = RTDirOpen(&hDir, pszPath); + if (RT_FAILURE(rc)) + return rtPathRmError(pOpts, pszPath, rc, "Error opening directory '%s': %Rrc", pszPath, rc); + int rcRet = VINF_SUCCESS; + for (;;) + { + /* + * Read the next entry, constructing an full path for it. + */ + size_t cbEntry = RTPATHRM_DIR_MAX_ENTRY_SIZE; + rc = RTDirReadEx(hDir, pDirEntry, &cbEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK); + if (rc == VERR_NO_MORE_FILES) + { + /* + * Reached the end of the directory. + */ + pszPath[cchPath] = '\0'; + rc = RTDirClose(hDir); + if (RT_FAILURE(rc)) + return rtPathRmError(pOpts, pszPath, rc, "Error closing directory '%s': %Rrc", pszPath, rc); + + /* Delete the directory. */ + int rc2 = rtPathRmOneDir(pOpts, pszPath); + if (RT_FAILURE(rc2) && RT_SUCCESS(rcRet)) + return rc2; + return rcRet; + } + + if (RT_FAILURE(rc)) + { + rc = rtPathRmError(pOpts, pszPath, rc, "Error reading directory '%s': %Rrc", pszPath, rc); + break; + } + + /* Skip '.' and '..'. */ + if ( pDirEntry->szName[0] == '.' + && ( pDirEntry->cbName == 1 + || ( pDirEntry->cbName == 2 + && pDirEntry->szName[1] == '.'))) + continue; + + /* Construct full path. */ + if (cchPath + pDirEntry->cbName >= RTPATH_MAX) + { + pszPath[cchPath] = '\0'; + rc = rtPathRmError(pOpts, pszPath, VERR_BUFFER_OVERFLOW, "Path buffer overflow in directory '%s'.", pszPath); + break; + } + memcpy(pszPath + cchPath, pDirEntry->szName, pDirEntry->cbName + 1); + + /* + * Take action according to the type. + */ + switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK) + { + case RTFS_TYPE_FILE: + rc = rtPathRmOneFile(pOpts, pszPath, &pDirEntry->Info); + break; + + case RTFS_TYPE_DIRECTORY: + rc = rtPathRmRecursive(pOpts, pszPath, cchPath + pDirEntry->cbName, pDirEntry); + break; + + case RTFS_TYPE_SYMLINK: + rc = rtPathRmOneSymlink(pOpts, pszPath); + break; + + case RTFS_TYPE_FIFO: + case RTFS_TYPE_DEV_CHAR: + case RTFS_TYPE_DEV_BLOCK: + case RTFS_TYPE_SOCKET: + rc = rtPathRmOneFile(pOpts, pszPath, &pDirEntry->Info); + break; + + case RTFS_TYPE_WHITEOUT: + default: + rc = rtPathRmError(pOpts, pszPath, VERR_UNEXPECTED_FS_OBJ_TYPE, + "Object '%s' has an unknown file type: %o\n", + pszPath, pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK); + break; + } + if (RT_FAILURE(rc) && RT_SUCCESS(rcRet)) + rcRet = rc; + } + + /* + * Some error occured, close and return. + */ + RTDirClose(hDir); + return rc; +} + +/** + * Validates the specified file or directory. + * + * @returns IPRT status code, errors go via rtPathRmError. + * @param pOpts The RM options. + * @param pszPath The path to the file, directory, whatever. + */ +static int rtPathRmOneValidate(PRTPATHRMCMDOPTS pOpts, const char *pszPath) +{ + /* + * RTPathFilename doesn't do the trailing slash thing the way we need it to. + * E.g. both '..' and '../' should be rejected. + */ + size_t cchPath = strlen(pszPath); + while (cchPath > 0 && RTPATH_IS_SLASH(pszPath[cchPath - 1])) + cchPath--; + + if ( ( cchPath == 0 + || 0 /** @todo drive letter + UNC crap */) + && pOpts->fPreserveRoot) + return rtPathRmError(pOpts, pszPath, VERR_CANT_DELETE_DIRECTORY, "Cannot remove root directory ('%s').\n", pszPath); + + size_t offLast = cchPath - 1; + while (offLast > 0 && !RTPATH_IS_SEP(pszPath[offLast - 1])) + offLast--; + + size_t cchLast = cchPath - offLast; + if ( pszPath[offLast] == '.' + && ( cchLast == 1 + || (cchLast == 2 && pszPath[offLast + 1] == '.'))) + return rtPathRmError(pOpts, pszPath, VERR_CANT_DELETE_DIRECTORY, "Cannot remove special directory '%s'.\n", pszPath); + + return VINF_SUCCESS; +} + + +/** + * Remove one user specified file or directory. + * + * @returns IPRT status code, errors go via rtPathRmError. + * @param pOpts The RM options. + * @param pszPath The path to the file, directory, whatever. + */ +static int rtPathRmOne(PRTPATHRMCMDOPTS pOpts, const char *pszPath) +{ + /* + * RM refuses to delete some directories. + */ + int rc = rtPathRmOneValidate(pOpts, pszPath); + if (RT_FAILURE(rc)) + return rc; + + /* + * Query file system object info. + */ + RTFSOBJINFO ObjInfo; + rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK); + if (RT_FAILURE(rc)) + { + if (pOpts->fForce && (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND)) + return VINF_SUCCESS; + return rtPathRmError(pOpts, pszPath, rc, "Error deleting '%s': %Rrc", pszPath, rc); + } + + /* + * Take type specific action. + */ + switch (ObjInfo.Attr.fMode & RTFS_TYPE_MASK) + { + case RTFS_TYPE_FILE: + return rtPathRmOneFile(pOpts, pszPath, &ObjInfo); + + case RTFS_TYPE_DIRECTORY: + if (pOpts->fRecursive) + { + char szPath[RTPATH_MAX]; + rc = RTPathAbs(pszPath, szPath, sizeof(szPath)); + if (RT_FAILURE(rc)) + return rtPathRmError(pOpts, pszPath, rc, "RTPathAbs failed on '%s': %Rrc\n", pszPath, rc); + + union + { + RTDIRENTRYEX Core; + uint8_t abPadding[RTPATHRM_DIR_MAX_ENTRY_SIZE]; + } DirEntry; + + return rtPathRmRecursive(pOpts, szPath, strlen(szPath), &DirEntry.Core); + } + if (pOpts->fDirsAndOther) + return rtPathRmOneDir(pOpts, pszPath); + return rtPathRmError(pOpts, pszPath, VERR_IS_A_DIRECTORY, "Cannot remove '%s': %Rrc\n", pszPath, VERR_IS_A_DIRECTORY); + + case RTFS_TYPE_SYMLINK: + return rtPathRmOneSymlink(pOpts, pszPath); + + case RTFS_TYPE_FIFO: + case RTFS_TYPE_DEV_CHAR: + case RTFS_TYPE_DEV_BLOCK: + case RTFS_TYPE_SOCKET: + return rtPathRmOneFile(pOpts, pszPath, &ObjInfo); + + case RTFS_TYPE_WHITEOUT: + default: + return rtPathRmError(pOpts, pszPath, VERR_UNEXPECTED_FS_OBJ_TYPE, + "Object '%s' has an unknown file type: %o\n", pszPath, ObjInfo.Attr.fMode & RTFS_TYPE_MASK); + + } +} + + +RTDECL(RTEXITCODE) RTPathRmCmd(unsigned cArgs, char **papszArgs) +{ + /* + * Parse the command line. + */ + static const RTGETOPTDEF s_aOptions[] = + { + /* operations */ + { "--dirs-and-more", 'd', RTGETOPT_REQ_NOTHING }, + { "--force", 'f', RTGETOPT_REQ_NOTHING }, + { "--prompt", 'i', RTGETOPT_REQ_NOTHING }, + { "--prompt-once", 'I', RTGETOPT_REQ_NOTHING }, + { "--interactive", RTPATHRMCMD_OPT_INTERACTIVE, RTGETOPT_REQ_STRING }, + { "--one-file-system", RTPATHRMCMD_OPT_ONE_FILE_SYSTEM, RTGETOPT_REQ_NOTHING }, + { "--preserve-root", RTPATHRMCMD_OPT_PRESERVE_ROOT, RTGETOPT_REQ_NOTHING }, + { "--no-preserve-root", RTPATHRMCMD_OPT_NO_PRESERVE_ROOT, RTGETOPT_REQ_NOTHING }, + { "--recursive", 'R', RTGETOPT_REQ_NOTHING }, + { "--recursive", 'r', RTGETOPT_REQ_NOTHING }, + { "--safe-delete", 'P', RTGETOPT_REQ_NOTHING }, + { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, + + /* IPRT extensions */ + { "--machine-readable", RTPATHRMCMD_OPT_MACHINE_READABLE, RTGETOPT_REQ_NOTHING }, + { "--machinereadable", RTPATHRMCMD_OPT_MACHINE_READABLE, RTGETOPT_REQ_NOTHING }, /* bad long option style */ + }; + + RTGETOPTSTATE GetState; + int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1, + RTGETOPTINIT_FLAGS_OPTS_FIRST); + if (RT_FAILURE(rc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOpt failed: %Rrc", rc); + + RTPATHRMCMDOPTS Opts; + RT_ZERO(Opts); + Opts.fPreserveRoot = true; + Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_NONE; + + RTGETOPTUNION ValueUnion; + while ( (rc = RTGetOpt(&GetState, &ValueUnion)) != 0 + && rc != VINF_GETOPT_NOT_OPTION) + { + switch (rc) + { + case 'd': + Opts.fDirsAndOther = true; + break; + + case 'f': + Opts.fForce = true; + Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_NONE; + break; + + case 'i': + Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_ALL; + break; + + case 'I': + Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_ONCE; + break; + + case RTPATHRMCMD_OPT_INTERACTIVE: + if (!strcmp(ValueUnion.psz, "always")) + Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_ALL; + else if (!strcmp(ValueUnion.psz, "once")) + Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_ONCE; + else + return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unknown --interactive option value: '%s'\n", ValueUnion.psz); + break; + + case RTPATHRMCMD_OPT_ONE_FILE_SYSTEM: + Opts.fOneFileSystem = true; + break; + + case RTPATHRMCMD_OPT_PRESERVE_ROOT: + Opts.fPreserveRoot = true; + break; + + case RTPATHRMCMD_OPT_NO_PRESERVE_ROOT: + Opts.fPreserveRoot = false; + break; + + case 'R': + case 'r': + Opts.fRecursive = true; + Opts.fDirsAndOther = true; + break; + + case 'P': + Opts.fSafeDelete = true; + break; + + case 'v': + Opts.fVerbose = true; + break; + + + case RTPATHRMCMD_OPT_MACHINE_READABLE: + Opts.fMachineReadable = true; + break; + + case 'h': + RTPrintf("Usage: to be written\nOption dump:\n"); + for (unsigned i = 0; i < RT_ELEMENTS(s_aOptions); i++) + if (RT_C_IS_PRINT(s_aOptions[i].iShort)) + RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong); + else + RTPrintf(" %s\n", s_aOptions[i].pszLong); + return RTEXITCODE_SUCCESS; + + case 'V': + RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision()); + return RTEXITCODE_SUCCESS; + + default: + return RTGetOptPrintError(rc, &ValueUnion); + } + } + + /* + * Options we don't support. + */ + if (Opts.fOneFileSystem) + return RTMsgErrorExit(RTEXITCODE_FAILURE, "The --one-file-system option is not yet implemented.\n"); + if (Opts.enmInteractive != RTPATHRMCMDINTERACTIVE_NONE) + return RTMsgErrorExit(RTEXITCODE_FAILURE, "The -i, -I and --interactive options are not implemented yet.\n"); + + /* + * No files means error. + */ + if (rc != VINF_GETOPT_NOT_OPTION && !Opts.fForce) + return RTMsgErrorExit(RTEXITCODE_FAILURE, "No files or directories specified.\n"); + + /* + * Machine readable init + header. + */ + if (Opts.fMachineReadable) + { + rc = RTStrmSetMode(g_pStdOut, true /*fBinary*/, false /*fCurrentCodeSet*/); + if (RT_FAILURE(rc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTStrmSetMode failed: %Rrc.\n", rc); + static const char s_achHeader[] = "hdr_id=rm\0hdr_ver=1"; + RTStrmWrite(g_pStdOut, s_achHeader, sizeof(s_achHeader)); + } + + /* + * Delete the specified files/dirs/whatever. + */ + RTEXITCODE rcExit = RTEXITCODE_SUCCESS; + while (rc == VINF_GETOPT_NOT_OPTION) + { + rc = rtPathRmOne(&Opts, ValueUnion.psz); + if (RT_FAILURE(rc)) + rcExit = RTEXITCODE_FAILURE; + + /* next */ + rc = RTGetOpt(&GetState, &ValueUnion); + } + if (rc != 0) + rcExit = RTGetOptPrintError(rc, &ValueUnion); + + /* + * Terminate the machine readable stuff. + */ + if (Opts.fMachineReadable) + { + RTStrmWrite(g_pStdOut, "\0\0\0", 4); + rc = RTStrmFlush(g_pStdOut); + if (RT_FAILURE(rc) && rcExit == RTEXITCODE_SUCCESS) + rcExit = RTEXITCODE_FAILURE; + } + + return rcExit; +} + diff --git a/src/VBox/Runtime/common/path/RTPathSplit.cpp b/src/VBox/Runtime/common/path/RTPathSplit.cpp new file mode 100644 index 00000000..6c528ce1 --- /dev/null +++ b/src/VBox/Runtime/common/path/RTPathSplit.cpp @@ -0,0 +1,133 @@ +/* $Id: RTPathSplit.cpp $ */ +/** @file + * IPRT - RTPathSplit + */ + +/* + * Copyright (C) 2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include "internal/iprt.h" +#include <iprt/path.h> + +#include <iprt/assert.h> +#include <iprt/err.h> +#include <iprt/string.h> + + + +RTDECL(int) RTPathSplit(const char *pszPath, PRTPATHSPLIT pSplit, size_t cbSplit, uint32_t fFlags) +{ + /* + * Input validation. + */ + AssertReturn(cbSplit >= RT_UOFFSETOF(RTPATHSPLIT, apszComps), VERR_INVALID_PARAMETER); + AssertPtrReturn(pSplit, VERR_INVALID_POINTER); + AssertPtrReturn(pszPath, VERR_INVALID_POINTER); + AssertReturn(*pszPath, VERR_PATH_ZERO_LENGTH); + AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, 0), VERR_INVALID_FLAGS); + + /* + * Use RTPathParse to do the parsing. + * - This makes the ASSUMPTION that the output of this function is greater + * or equal to that of RTPathParsed. + * - We're aliasing the buffer here, so use volatile to avoid issues due to + * compiler optimizations. + */ + RTPATHPARSED volatile *pParsedVolatile = (RTPATHPARSED volatile *)pSplit; + RTPATHSPLIT volatile *pSplitVolatile = (RTPATHSPLIT volatile *)pSplit; + + AssertCompile(sizeof(*pParsedVolatile) <= sizeof(*pSplitVolatile)); + AssertCompile(sizeof(pParsedVolatile->aComps[0]) <= sizeof(pSplitVolatile->apszComps[0])); + + int rc = RTPathParse(pszPath, (PRTPATHPARSED)pParsedVolatile, cbSplit, fFlags); + if (RT_FAILURE(rc) && rc != VERR_BUFFER_OVERFLOW) + return rc; + + /* + * Calculate the required buffer space. + */ + uint16_t const cComps = pParsedVolatile->cComps; + uint16_t const fProps = pParsedVolatile->fProps; + uint16_t const cchPath = pParsedVolatile->cchPath; + uint16_t const offSuffix = pParsedVolatile->offSuffix; + uint32_t cbNeeded = RT_OFFSETOF(RTPATHSPLIT, apszComps[cComps]) + + cchPath + + RTPATH_PROP_FIRST_NEEDS_NO_SLASH(fProps) /* zero terminator for root spec. */ + - RT_BOOL(fProps & RTPATH_PROP_DIR_SLASH) /* counted by cchPath, not included in the comp str. */ + + 1; /* zero terminator. */ + if (cbNeeded > cbSplit) + { + pSplitVolatile->cbNeeded = cbNeeded; + return VERR_BUFFER_OVERFLOW; + } + Assert(RT_SUCCESS(rc)); + + /* + * Convert the array and copy the strings, both backwards. + */ + char *psz = (char *)pSplit + cbNeeded; + uint32_t idxComp = cComps - 1; + + /* the final component first (because of suffix handling). */ + uint16_t offComp = pParsedVolatile->aComps[idxComp].off; + uint16_t cchComp = pParsedVolatile->aComps[idxComp].cch; + + *--psz = '\0'; + psz -= cchComp; + memcpy(psz, &pszPath[offComp], cchComp); + pSplitVolatile->apszComps[idxComp] = psz; + + char *pszSuffix; + if (offSuffix >= offComp + cchComp) + pszSuffix = &psz[cchComp]; + else + pszSuffix = &psz[offSuffix - offComp]; + + /* the remainder */ + while (idxComp-- > 0) + { + offComp = pParsedVolatile->aComps[idxComp].off; + cchComp = pParsedVolatile->aComps[idxComp].cch; + *--psz = '\0'; + psz -= cchComp; + memcpy(psz, &pszPath[offComp], cchComp); + pSplitVolatile->apszComps[idxComp] = psz; + } + + /* + * Store / reshuffle the non-array bits. This MUST be done after finishing + * the array processing because there may be members in RTPATHSPLIT + * overlapping the array of RTPATHPARSED. + */ + AssertCompileMembersSameSizeAndOffset(RTPATHPARSED, cComps, RTPATHSPLIT, cComps); Assert(pSplitVolatile->cComps == cComps); + AssertCompileMembersSameSizeAndOffset(RTPATHPARSED, fProps, RTPATHSPLIT, fProps); Assert(pSplitVolatile->fProps == fProps); + AssertCompileMembersSameSizeAndOffset(RTPATHPARSED, cchPath, RTPATHSPLIT, cchPath); Assert(pSplitVolatile->cchPath == cchPath); + pSplitVolatile->u16Reserved = 0; + pSplitVolatile->cbNeeded = cbNeeded; + pSplitVolatile->pszSuffix = pszSuffix; + + return rc; +} + diff --git a/src/VBox/Runtime/common/path/RTPathSplitA.cpp b/src/VBox/Runtime/common/path/RTPathSplitA.cpp new file mode 100644 index 00000000..e29d315d --- /dev/null +++ b/src/VBox/Runtime/common/path/RTPathSplitA.cpp @@ -0,0 +1,91 @@ +/* $Id: RTPathSplitA.cpp $ */ +/** @file + * IPRT - RTPathSplitA and RTPathSplitFree. + */ + +/* + * Copyright (C) 2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include "internal/iprt.h" +#include <iprt/path.h> + +#include <iprt/assert.h> +#include <iprt/err.h> +#include <iprt/mem.h> +#include <iprt/string.h> + + + +RTDECL(int) RTPathSplitATag(const char *pszPath, PRTPATHSPLIT *ppSplit, uint32_t fFlags, const char *pszTag) +{ + AssertPtrReturn(ppSplit, VERR_INVALID_POINTER); + *ppSplit = NULL; + + /* + * Try estimate a reasonable buffer size based on the path length. + * Note! No point in trying very hard to get it right. + */ + size_t cbSplit = strlen(pszPath); + cbSplit += RT_OFFSETOF(RTPATHSPLIT, apszComps[cbSplit / 8]) + cbSplit / 8 + 8; + cbSplit = RT_ALIGN(cbSplit, 64); + PRTPATHSPLIT pSplit = (PRTPATHSPLIT)RTMemAllocTag(cbSplit, pszTag); + if (pSplit == NULL) + return VERR_NO_MEMORY; + + /* + * First try. If it fails due to buffer, reallocate the buffer and try again. + */ + int rc = RTPathSplit(pszPath, pSplit, cbSplit, fFlags); + if (rc == VERR_BUFFER_OVERFLOW) + { + cbSplit = RT_ALIGN(pSplit->cbNeeded, 64); + RTMemFree(pSplit); + + pSplit = (PRTPATHSPLIT)RTMemAllocTag(cbSplit, pszTag); + if (pSplit == NULL) + return VERR_NO_MEMORY; + rc = RTPathSplit(pszPath, pSplit, cbSplit, fFlags); + } + + /* + * Done (one way or the other). + */ + if (RT_SUCCESS(rc)) + *ppSplit = pSplit; + else + RTMemFree(pSplit); + return rc; +} + + +RTDECL(void) RTPathSplitFree(PRTPATHSPLIT pSplit) +{ + if (pSplit) + { + Assert(pSplit->u16Reserved = UINT16_C(0xbeef)); + RTMemFree(pSplit); + } +} + diff --git a/src/VBox/Runtime/common/path/RTPathSplitReassemble.cpp b/src/VBox/Runtime/common/path/RTPathSplitReassemble.cpp new file mode 100644 index 00000000..8d703171 --- /dev/null +++ b/src/VBox/Runtime/common/path/RTPathSplitReassemble.cpp @@ -0,0 +1,120 @@ +/* $Id: RTPathSplitReassemble.cpp $ */ +/** @file + * IPRT - RTPathSplitReassemble. + */ + +/* + * Copyright (C) 2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include "internal/iprt.h" +#include <iprt/path.h> + +#include <iprt/assert.h> +#include <iprt/err.h> +#include <iprt/string.h> + + +RTDECL(int) RTPathSplitReassemble(PRTPATHSPLIT pSplit, uint32_t fFlags, char *pszDstPath, size_t cbDstPath) +{ + /* + * Input validation. + */ + AssertPtrReturn(pSplit, VERR_INVALID_POINTER); + AssertReturn(pSplit->cComps > 0, VERR_INVALID_PARAMETER); + AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, 0) && !(fFlags & RTPATH_STR_F_MIDDLE), VERR_INVALID_FLAGS); + AssertPtrReturn(pszDstPath, VERR_INVALID_POINTER); + AssertReturn(cbDstPath > pSplit->cchPath, VERR_BUFFER_OVERFLOW); + + /* + * Figure which slash to use. + */ + char chSlash; + switch (fFlags & RTPATH_STR_F_STYLE_MASK) + { + case RTPATH_STR_F_STYLE_HOST: + chSlash = RTPATH_SLASH; + break; + + case RTPATH_STR_F_STYLE_DOS: + chSlash = '\\'; + break; + + case RTPATH_STR_F_STYLE_UNIX: + chSlash = '/'; + break; + + default: + AssertFailedReturn(VERR_INVALID_FLAGS); /* impossible */ + } + + /* + * Do the joining. + */ + uint32_t const cchOrgPath = pSplit->cchPath; + size_t cchDstPath = 0; + uint32_t const cComps = pSplit->cComps; + uint32_t idxComp = 0; + char *pszDst = pszDstPath; + size_t cchComp; + + if (RTPATH_PROP_HAS_ROOT_SPEC(pSplit->fProps)) + { + cchComp = strlen(pSplit->apszComps[0]); + cchDstPath += cchComp; + AssertReturn(cchDstPath <= cchOrgPath, VERR_INVALID_PARAMETER); + memcpy(pszDst, pSplit->apszComps[0], cchComp); + + /* fix the slashes */ + char chOtherSlash = chSlash == '\\' ? '/' : '\\'; + while (cchComp-- > 0) + { + if (*pszDst == chOtherSlash) + *pszDst = chSlash; + pszDst++; + } + idxComp = 1; + } + + while (idxComp < cComps) + { + cchComp = strlen(pSplit->apszComps[idxComp]); + cchDstPath += cchComp; + AssertReturn(cchDstPath <= cchOrgPath, VERR_INVALID_PARAMETER); + memcpy(pszDst, pSplit->apszComps[idxComp], cchComp); + pszDst += cchComp; + idxComp++; + if (idxComp != cComps || (pSplit->fProps & RTPATH_PROP_DIR_SLASH)) + { + cchDstPath++; + AssertReturn(cchDstPath <= cchOrgPath, VERR_INVALID_PARAMETER); + *pszDst++ = chSlash; + } + } + + *pszDst = '\0'; + + return VINF_SUCCESS; +} + diff --git a/src/VBox/Runtime/common/path/RTPathStripExt.cpp b/src/VBox/Runtime/common/path/RTPathStripExt.cpp index 789bb3e9..8156f6a0 100644 --- a/src/VBox/Runtime/common/path/RTPathStripExt.cpp +++ b/src/VBox/Runtime/common/path/RTPathStripExt.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/RTPathStripFilename.cpp b/src/VBox/Runtime/common/path/RTPathStripFilename.cpp index 3db34165..b2647833 100644 --- a/src/VBox/Runtime/common/path/RTPathStripFilename.cpp +++ b/src/VBox/Runtime/common/path/RTPathStripFilename.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/RTPathTraverseList.cpp b/src/VBox/Runtime/common/path/RTPathTraverseList.cpp index daa88dce..361b0f82 100644 --- a/src/VBox/Runtime/common/path/RTPathTraverseList.cpp +++ b/src/VBox/Runtime/common/path/RTPathTraverseList.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009 Oracle Corporation + * Copyright (C) 2009-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/comparepaths.cpp b/src/VBox/Runtime/common/path/comparepaths.cpp index 40271362..bfa5e71c 100644 --- a/src/VBox/Runtime/common/path/comparepaths.cpp +++ b/src/VBox/Runtime/common/path/comparepaths.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/rtPathRootSpecLen.cpp b/src/VBox/Runtime/common/path/rtPathRootSpecLen.cpp index 92c91136..9cdbb400 100644 --- a/src/VBox/Runtime/common/path/rtPathRootSpecLen.cpp +++ b/src/VBox/Runtime/common/path/rtPathRootSpecLen.cpp @@ -54,7 +54,7 @@ DECLHIDDEN(size_t) rtPathRootSpecLen(const char *pszPath) size_t off = 0; if (RTPATH_IS_SLASH(pszPath[0])) { -#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS) +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) if ( RTPATH_IS_SLASH(pszPath[1]) && !RTPATH_IS_SLASH(pszPath[2]) && pszPath[2]) @@ -78,7 +78,7 @@ DECLHIDDEN(size_t) rtPathRootSpecLen(const char *pszPath) while (RTPATH_IS_SLASH(pszPath[off])) off++; } -#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS) +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) else if (RT_C_IS_ALPHA(pszPath[0]) && pszPath[1] == ':') { off = 2; diff --git a/src/VBox/Runtime/common/path/rtPathVolumeSpecLen.cpp b/src/VBox/Runtime/common/path/rtPathVolumeSpecLen.cpp index c80c7976..5e95e5d9 100644 --- a/src/VBox/Runtime/common/path/rtPathVolumeSpecLen.cpp +++ b/src/VBox/Runtime/common/path/rtPathVolumeSpecLen.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/common/path/rtpath-expand-template.cpp.h b/src/VBox/Runtime/common/path/rtpath-expand-template.cpp.h new file mode 100644 index 00000000..3797733a --- /dev/null +++ b/src/VBox/Runtime/common/path/rtpath-expand-template.cpp.h @@ -0,0 +1,82 @@ +/* $Id: rtpath-expand-template.cpp.h $ */ +/** @file + * IPRT - RTPath - Internal header that includes RTPATH_TEMPLATE_CPP_H multiple + * times to expand the code for different path styles. + */ + +/* + * Copyright (C) 2006-2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + +#undef RTPATH_DELIMITER + +/* + * DOS style + */ +#undef RTPATH_STYLE +#undef RTPATH_SLASH +#undef RTPATH_SLASH_STR +#undef RTPATH_IS_SLASH +#undef RTPATH_IS_VOLSEP +#undef RTPATH_STYLE_FN + +#define RTPATH_STYLE RTPATH_STR_F_STYLE_DOS +#define RTPATH_SLASH '\\' +#define RTPATH_SLASH_STR "\\" +#define RTPATH_IS_SLASH(a_ch) ( (a_ch) == '\\' || (a_ch) == '/' ) +#define RTPATH_IS_VOLSEP(a_ch) ( (a_ch) == ':' ) +#define RTPATH_STYLE_FN(a_Name) a_Name ## StyleDos +#include RTPATH_TEMPLATE_CPP_H + +/* + * Unix style. + */ +#undef RTPATH_STYLE +#undef RTPATH_SLASH +#undef RTPATH_SLASH_STR +#undef RTPATH_IS_SLASH +#undef RTPATH_IS_VOLSEP +#undef RTPATH_STYLE_FN + +#define RTPATH_STYLE RTPATH_STR_F_STYLE_UNIX +#define RTPATH_SLASH '/' +#define RTPATH_SLASH_STR "/" +#define RTPATH_IS_SLASH(a_ch) ( (a_ch) == '/' ) +#define RTPATH_IS_VOLSEP(a_ch) ( false ) +#define RTPATH_STYLE_FN(a_Name) a_Name ## StyleUnix +#include RTPATH_TEMPLATE_CPP_H + +/* + * Clean up and restore the host style. + */ +#undef RTPATH_STYLE_FN +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) +# undef RTPATH_STYLE +# undef RTPATH_SLASH +# undef RTPATH_SLASH_STR +# undef RTPATH_IS_SLASH +# undef RTPATH_IS_VOLSEP +# define RTPATH_STYLE RTPATH_STR_F_STYLE_DOS +# define RTPATH_SLASH '\\' +# define RTPATH_SLASH_STR "\\" +# define RTPATH_IS_SLASH(a_ch) ( (a_ch) == '\\' || (a_ch) == '/' ) +# define RTPATH_IS_VOLSEP(a_ch) ( (a_ch) == ':' ) +#endif + |