VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/path/RTPathCalcRelative.cpp@ 67849

Last change on this file since 67849 was 62477, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.5 KB
Line 
1/* $Id: RTPathCalcRelative.cpp 62477 2016-07-22 18:27:37Z vboxsync $ */
2/** @file
3 * IPRT - RTPathCreateRelative.
4 */
5
6/*
7 * Copyright (C) 2013-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "internal/iprt.h"
32#include <iprt/path.h>
33#include <iprt/assert.h>
34#include <iprt/err.h>
35#include <iprt/string.h>
36#include "internal/path.h"
37
38
39
40RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst,
41 const char *pszPathFrom,
42 const char *pszPathTo)
43{
44 int rc = VINF_SUCCESS;
45
46 AssertPtrReturn(pszPathDst, VERR_INVALID_POINTER);
47 AssertReturn(cbPathDst, VERR_INVALID_PARAMETER);
48 AssertPtrReturn(pszPathFrom, VERR_INVALID_POINTER);
49 AssertPtrReturn(pszPathTo, VERR_INVALID_POINTER);
50 AssertReturn(RTPathStartsWithRoot(pszPathFrom), VERR_INVALID_PARAMETER);
51 AssertReturn(RTPathStartsWithRoot(pszPathTo), VERR_INVALID_PARAMETER);
52 AssertReturn(RTStrCmp(pszPathFrom, pszPathTo), VERR_INVALID_PARAMETER);
53
54 /*
55 * Check for different root specifiers (drive letters), creating a relative path doesn't work here.
56 * @todo: How to handle case insensitive root specifiers correctly?
57 */
58 size_t offRootFrom = rtPathRootSpecLen(pszPathFrom);
59 size_t offRootTo = rtPathRootSpecLen(pszPathTo);
60
61 if ( offRootFrom != offRootTo
62 || RTStrNCmp(pszPathFrom, pszPathTo, offRootFrom))
63 return VERR_NOT_SUPPORTED;
64
65 /* Filter out the parent path which is equal to both paths. */
66 while ( *pszPathFrom == *pszPathTo
67 && *pszPathFrom != '\0'
68 && *pszPathTo != '\0')
69 {
70 pszPathFrom++;
71 pszPathTo++;
72 }
73
74 /*
75 * Because path components can start with an equal string but differ afterwards we
76 * need to go back to the beginning of the current component.
77 */
78 while (!RTPATH_IS_SEP(*pszPathFrom))
79 pszPathFrom--;
80
81 pszPathFrom++; /* Skip path separator. */
82
83 while (!RTPATH_IS_SEP(*pszPathTo))
84 pszPathTo--;
85
86 pszPathTo++; /* Skip path separator. */
87
88 /* Paths point to the first non equal component now. */
89 char aszPathTmp[RTPATH_MAX + 1];
90 unsigned offPathTmp = 0;
91
92 /* Create the part to go up from pszPathFrom. */
93 while (*pszPathFrom != '\0')
94 {
95 while ( !RTPATH_IS_SEP(*pszPathFrom)
96 && *pszPathFrom != '\0')
97 pszPathFrom++;
98
99 if (RTPATH_IS_SEP(*pszPathFrom))
100 {
101 if (offPathTmp + 3 >= sizeof(aszPathTmp) - 1)
102 return VERR_FILENAME_TOO_LONG;
103 aszPathTmp[offPathTmp++] = '.';
104 aszPathTmp[offPathTmp++] = '.';
105 aszPathTmp[offPathTmp++] = RTPATH_SLASH;
106 pszPathFrom++;
107 }
108 }
109
110 aszPathTmp[offPathTmp] = '\0';
111
112 /* Now append the rest of pszPathTo to the final path. */
113 char *pszPathTmp = &aszPathTmp[offPathTmp];
114 size_t cbPathTmp = sizeof(aszPathTmp) - offPathTmp - 1;
115 rc = RTStrCatP(&pszPathTmp, &cbPathTmp, pszPathTo);
116 if (RT_SUCCESS(rc))
117 {
118 *pszPathTmp = '\0';
119
120 size_t cchPathTmp = strlen(aszPathTmp);
121 if (cchPathTmp >= cbPathDst)
122 return VERR_BUFFER_OVERFLOW;
123 memcpy(pszPathDst, aszPathTmp, cchPathTmp + 1);
124 }
125 else
126 rc = VERR_FILENAME_TOO_LONG;
127
128 return rc;
129}
130
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette