Move some stuff from path_helper to file_dirvol, and simplify

Change-Id: Ic9dcff74c16e5f9c107ca060a3d22866f552c398
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163632
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
Mike Kaganski 2024-02-20 13:45:12 +06:00
parent 7751ad7288
commit 43f49c3b50
5 changed files with 76 additions and 197 deletions

View file

@ -232,7 +232,6 @@ $(eval $(call gb_Library_add_exception_objects,sal,\
sal/osl/w32/module \
sal/osl/w32/mutex \
sal/osl/w32/nlsupport \
sal/osl/w32/path_helper \
sal/osl/w32/pipe \
sal/osl/w32/process \
sal/osl/w32/procimpl \

View file

@ -481,7 +481,7 @@ static int path_make_parent(char* path)
return 0;
}
static int create_dir_with_callback(
static oslFileError create_dir_with_callback(
char* directory_path,
oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
void* pData)
@ -494,9 +494,9 @@ static int create_dir_with_callback(
osl::detail::convertPathnameToUrl(directory_path, &url);
aDirectoryCreationCallbackFunc(pData, url.pData);
}
return 0;
return osl_File_E_None;
}
return errno;
return oslTranslateFileError(errno);
}
static oslFileError create_dir_recursively_(
@ -507,14 +507,11 @@ static oslFileError create_dir_recursively_(
OSL_PRECOND((rtl_str_getLength(dir_path) > 0) && ((dir_path + (rtl_str_getLength(dir_path) - 1)) != (dir_path + rtl_str_lastIndexOfChar(dir_path, '/'))),
"Path must not end with a slash");
int native_err = create_dir_with_callback(
oslFileError osl_error = create_dir_with_callback(
dir_path, aDirectoryCreationCallbackFunc, pData);
if (native_err == 0)
return osl_File_E_None;
if (native_err != ENOENT)
return oslTranslateFileError(native_err);
if (osl_error != osl_File_E_NOENT)
return osl_error;
// we step back until '/a_dir' at maximum because
// we should get an error unequal ENOENT when
@ -522,7 +519,7 @@ static oslFileError create_dir_recursively_(
// return before
int pos = path_make_parent(dir_path);
oslFileError osl_error = create_dir_recursively_(
osl_error = create_dir_recursively_(
dir_path, aDirectoryCreationCallbackFunc, pData);
if (osl_error != osl_File_E_None && osl_error != osl_File_E_EXIST)
@ -530,7 +527,7 @@ static oslFileError create_dir_recursively_(
dir_path[pos] = '/';
return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
return create_dir_with_callback(dir_path, aDirectoryCreationCallbackFunc, pData);
}
oslFileError SAL_CALL osl_createDirectoryPath(

View file

@ -31,7 +31,6 @@
#include <sal/log.hxx>
#include <o3tl/char16_t2wchar_t.hxx>
const wchar_t UNC_PREFIX[] = L"\\\\";
const wchar_t BACKSLASH = '\\';
const wchar_t SLASH = '/';
@ -99,18 +98,50 @@ BOOL FileTimeToTimeValue(const FILETIME *cpFTime, TimeValue *pTimeVal)
namespace
{
// Returns whether a given path is only a logical drive pattern or not.
// A logical drive pattern is something like "a:\", "c:\".
// No logical drive pattern is something like "c:\test"
bool systemPathIsLogicalDrivePattern(std::u16string_view path)
{
// is [A-Za-z]:[/|\]\0
if (path.length() < 2 || !rtl::isAsciiAlpha(path[0]) || path[1] != ':')
return false;
auto rest = path.substr(2);
return rest.empty() // "c:"
|| rest == u"\\" // "c:\"
|| rest == u"/" // "c:/"
|| rest == u".\\"; // "c:.\"
// degenerated case returned by the Windows FileOpen dialog
// when someone enters for instance "x:filename", the Win32
// API accepts this case
}
// Adds a trailing path separator to the given system path if not
// already there and if the path is not the root path or a logical
// drive alone
void systemPathEnsureSeparator(/*inout*/ OUString& path)
{
if (!path.endsWith(u"\\") && !path.endsWith(u"/"))
path += "\\";
SAL_WARN_IF(!path.endsWith(u"\\"), "sal.osl",
"systemPathEnsureSeparator: Post condition failed");
}
// Removes the last separator from the given system path if any and
// if the path is not the root path '\'
void systemPathRemoveSeparator(/*inout*/ OUString& path)
{
if (!systemPathIsLogicalDrivePattern(path) && (path.endsWith(u"\\") || path.endsWith(u"/")))
path = path.copy(0, path.getLength() - 1);
}
struct Component
{
Component() :
begin_(nullptr), end_(nullptr)
{}
bool isPresent() const { return begin_ < end_; }
bool isPresent() const
{ return (static_cast<sal_IntPtr>(end_ - begin_) > 0); }
const sal_Unicode* begin_;
const sal_Unicode* end_;
const sal_Unicode* begin_ = nullptr;
const sal_Unicode* end_ = nullptr;
};
struct UNCComponents
@ -120,47 +151,48 @@ namespace
Component resource_;
};
bool is_UNC_path(const sal_Unicode* path)
{ return (0 == wcsncmp(UNC_PREFIX, o3tl::toW(path), SAL_N_ELEMENTS(UNC_PREFIX) - 1)); }
bool is_UNC_path(std::u16string_view path) { return path.starts_with(u"\\\\"); }
void parse_UNC_path(const sal_Unicode* path, UNCComponents* puncc)
UNCComponents parse_UNC_path(std::u16string_view path)
{
OSL_PRECOND(is_UNC_path(path), "Precondition violated: No UNC path");
OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) == -1, "Path must not contain slashes");
OSL_PRECOND(path.find('/') == std::u16string_view::npos, "Path must not contain slashes");
const sal_Unicode* pend = path + rtl_ustr_getLength(path);
const sal_Unicode* ppos = path + 2;
const sal_Unicode* pend = path.data() + path.length();
const sal_Unicode* ppos = path.data() + 2;
UNCComponents uncc;
puncc->server_.begin_ = ppos;
uncc.server_.begin_ = ppos;
while ((ppos < pend) && (*ppos != BACKSLASH))
ppos++;
puncc->server_.end_ = ppos;
uncc.server_.end_ = ppos;
if (BACKSLASH == *ppos)
if (ppos < pend)
{
puncc->share_.begin_ = ++ppos;
uncc.share_.begin_ = ++ppos;
while ((ppos < pend) && (*ppos != BACKSLASH))
ppos++;
puncc->share_.end_ = ppos;
uncc.share_.end_ = ppos;
if (BACKSLASH == *ppos)
if (ppos < pend)
{
puncc->resource_.begin_ = ++ppos;
uncc.resource_.begin_ = ++ppos;
while (ppos < pend)
ppos++;
puncc->resource_.end_ = ppos;
uncc.resource_.end_ = ppos;
}
}
SAL_WARN_IF(!puncc->server_.isPresent() || !puncc->share_.isPresent(),
SAL_WARN_IF(!uncc.server_.isPresent() || !uncc.share_.isPresent(),
"sal.osl",
"Postcondition violated: Invalid UNC path detected");
return uncc;
}
bool has_path_parent(const sal_Unicode* path)
bool has_path_parent(std::u16string_view path)
{
// Has the given path a parent or are we already there,
// e.g. 'c:\' or '\\server\share\'?
@ -168,20 +200,15 @@ namespace
bool has_parent = false;
if (is_UNC_path(path))
{
UNCComponents unc_comp;
parse_UNC_path(path, &unc_comp);
UNCComponents unc_comp = parse_UNC_path(path);
has_parent = unc_comp.resource_.isPresent();
}
else
{
has_parent = !osl::systemPathIsLogicalDrivePattern(OUString(path));
has_parent = !systemPathIsLogicalDrivePattern(path);
}
return has_parent;
}
bool has_path_parent(const OUString& path)
{ return has_path_parent(path.getStr()); }
}
oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
@ -597,9 +624,6 @@ static DWORD create_dir_recursively_(
DWORD w32_error = create_dir_with_callback(
dir_path, aDirectoryCreationCallbackFunc, pData);
if (w32_error == ERROR_SUCCESS)
return ERROR_SUCCESS;
if ((w32_error != ERROR_PATH_NOT_FOUND) || !has_path_parent(dir_path->buffer))
return w32_error;
@ -613,7 +637,7 @@ static DWORD create_dir_recursively_(
if (ERROR_SUCCESS != w32_error && ERROR_ALREADY_EXISTS != w32_error)
return w32_error;
return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
return create_dir_with_callback(dir_path, aDirectoryCreationCallbackFunc, pData);
}
oslFileError SAL_CALL osl_createDirectoryPath(
@ -631,7 +655,7 @@ oslFileError SAL_CALL osl_createDirectoryPath(
if (osl_error != osl_File_E_None)
return osl_error;
osl::systemPathRemoveSeparator(sys_path);
systemPathRemoveSeparator(sys_path);
return oslTranslateFileError(create_dir_recursively_(
sys_path.pData, aDirectoryCreationCallbackFunc, pData));
@ -1073,7 +1097,7 @@ static bool is_floppy_volume_mount_point(const OUString& path)
static const LPCWSTR FLOPPY_B = L"B:\\";
OUString p(path);
osl::systemPathEnsureSeparator(p);
systemPathEnsureSeparator(p);
WCHAR vn[51];
if (GetVolumeNameForVolumeMountPointW(o3tl::toW(p.getStr()), vn, SAL_N_ELEMENTS(vn)))
@ -1109,7 +1133,7 @@ static bool is_floppy_drive(const OUString& path)
static bool is_volume_mount_point(const OUString& path)
{
OUString p(path);
osl::systemPathRemoveSeparator(p);
systemPathRemoveSeparator(p);
if (is_floppy_drive(p))
return false;
@ -1140,7 +1164,7 @@ static UINT get_volume_mount_point_drive_type(const OUString& path)
return GetDriveTypeW(nullptr);
OUString p(path);
osl::systemPathEnsureSeparator(p);
systemPathEnsureSeparator(p);
WCHAR vn[51];
if (GetVolumeNameForVolumeMountPointW(o3tl::toW(p.getStr()), vn, SAL_N_ELEMENTS(vn)))
@ -1312,7 +1336,7 @@ static void path_travel_to_volume_root(const OUString& system_path, OUString& vo
/**/;
volume_root = sys_path;
osl::systemPathEnsureSeparator(volume_root);
systemPathEnsureSeparator(volume_root);
}
oslFileError SAL_CALL osl_getVolumeInformation(

View file

@ -1,89 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "path_helper.hxx"
#include <osl/diagnose.h>
#include <rtl/ustring.hxx>
#include <sal/log.hxx>
#include <algorithm>
#include <wchar.h>
constexpr OUString BACKSLASH (u"\\"_ustr);
constexpr OUString SLASH (u"/"_ustr);
void osl_systemPathEnsureSeparator(/*inout*/ rtl_uString** ppustrPath)
{
OSL_PRECOND(ppustrPath && (nullptr != *ppustrPath),
"osl_systemPathEnsureSeparator: Invalid parameter");
OUString path(*ppustrPath);
sal_Int32 i = std::max<sal_Int32>(path.lastIndexOf(BACKSLASH), path.lastIndexOf(SLASH));
if (i < (path.getLength()-1))
{
path += BACKSLASH;
rtl_uString_assign(ppustrPath, path.pData);
}
SAL_WARN_IF( !path.endsWith(BACKSLASH),
"sal.osl",
"osl_systemPathEnsureSeparator: Post condition failed");
}
void osl_systemPathRemoveSeparator(/*inout*/ rtl_uString** ppustrPath)
{
OUString path(*ppustrPath);
if (!osl::systemPathIsLogicalDrivePattern(path))
{
sal_Int32 i = std::max<sal_Int32>(path.lastIndexOf(BACKSLASH), path.lastIndexOf(SLASH));
if (i > -1 && (i == (path.getLength() - 1)))
{
path = path.copy(0, path.getLength() - 1);
rtl_uString_assign(ppustrPath, path.pData);
}
}
}
// is [A-Za-z]:[/|\]\0
const char* const LDP = ":";
const char* const LDP_WITH_BACKSLASH = ":\\";
const char* const LDP_WITH_SLASH = ":/";
// degenerated case returned by the Windows FileOpen dialog
// when someone enters for instance "x:filename", the Win32
// API accepts this case
const char* const LDP_WITH_DOT_BACKSLASH = ":.\\";
bool osl_systemPathIsLogicalDrivePattern(/*in*/ const rtl_uString* pustrPath)
{
const sal_Unicode* p = rtl_uString_getStr(const_cast<rtl_uString*>(pustrPath));
if (iswalpha(*p++))
{
return ((0 == rtl_ustr_ascii_compare(p, LDP)) ||
(0 == rtl_ustr_ascii_compare(p, LDP_WITH_BACKSLASH)) ||
(0 == rtl_ustr_ascii_compare(p, LDP_WITH_SLASH)) ||
(0 == rtl_ustr_ascii_compare(p, LDP_WITH_DOT_BACKSLASH)));
}
return false;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -23,71 +23,19 @@
#include <sal/config.h>
#include <osl/diagnose.h>
#include <rtl/ustring.h>
#include <rtl/ustring.hxx>
#include <sal/types.h>
/**
Adds a trailing path separator to the given system path if not
already there and if the path is not the root path or a logical
drive alone
*/
void osl_systemPathEnsureSeparator(/*inout*/ rtl_uString** ppustrPath);
/**
Removes the last separator from the given system path if any and
if the path is not the root path '\'
*/
void osl_systemPathRemoveSeparator(/*inout*/ rtl_uString** ppustrPath);
/**
Returns whether a given path is only a logical drive pattern or not.
A logical drive pattern is something like "a:\", "c:\".
No logical drive pattern is something like "c:\test"
*/
bool osl_systemPathIsLogicalDrivePattern(/*in*/ const rtl_uString* pustrPath);
namespace osl
{
/**
Adds a trailing path separator to the given system path if not
already there and if the path is not the root path or a logical
drive alone
*/
inline void systemPathEnsureSeparator(/*inout*/ OUString& Path)
{
osl_systemPathEnsureSeparator(&Path.pData);
}
/**
Removes the last separator from the given system path if any and
if the path is not the root path '\'
*/
inline void systemPathRemoveSeparator(/*inout*/ OUString& Path)
{
osl_systemPathRemoveSeparator(&Path.pData);
}
inline bool systemPathIsLogicalDrivePattern(/*in*/ const OUString& path)
{
return osl_systemPathIsLogicalDrivePattern(path.pData);
}
template< class T >
class LongPathBuffer
{
T* m_pBuffer;
sal_uInt32 m_nCharNum;
LongPathBuffer();
LongPathBuffer( const LongPathBuffer& );
LongPathBuffer& operator=( const LongPathBuffer& );
LongPathBuffer() = delete;
LongPathBuffer(const LongPathBuffer&) = delete;
LongPathBuffer& operator=(const LongPathBuffer&) = delete;
public:
explicit LongPathBuffer( sal_uInt32 nCharNum )