~ubuntu-branches/ubuntu/trusty/virtualbox-lts-xenial/trusty-proposed

« back to all changes in this revision

Viewing changes to src/VBox/Runtime/common/path/RTPathCalcRelative.cpp

  • Committer: Package Import Robot
  • Author(s): Gianfranco Costamagna
  • Date: 2016-02-23 14:28:26 UTC
  • Revision ID: package-import@ubuntu.com-20160223142826-bdu69el2z6wa2a44
Tags: upstream-4.3.36-dfsg
ImportĀ upstreamĀ versionĀ 4.3.36-dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: RTPathCalcRelative.cpp $ */
 
2
/** @file
 
3
 * IPRT - RTPathCreateRelative.
 
4
 */
 
5
 
 
6
/*
 
7
 * Copyright (C) 2013 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
 
 
40
RTDECL(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