mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
Merge pull request #47533 from twangboy/fix_47178
Fix issues with functions that use makedirs on Windows
This commit is contained in:
commit
d56ddad22c
@ -662,13 +662,13 @@ def _error(ret, err_msg):
|
||||
|
||||
|
||||
def _check_directory(name,
|
||||
user,
|
||||
group,
|
||||
recurse,
|
||||
mode,
|
||||
clean,
|
||||
require,
|
||||
exclude_pat,
|
||||
user=None,
|
||||
group=None,
|
||||
recurse=False,
|
||||
mode=None,
|
||||
clean=False,
|
||||
require=False,
|
||||
exclude_pat=None,
|
||||
max_depth=None,
|
||||
follow_symlinks=False):
|
||||
'''
|
||||
@ -753,7 +753,7 @@ def _check_directory(name,
|
||||
|
||||
|
||||
def _check_directory_win(name,
|
||||
win_owner,
|
||||
win_owner=None,
|
||||
win_perms=None,
|
||||
win_deny_perms=None,
|
||||
win_inheritance=None):
|
||||
@ -766,6 +766,7 @@ def _check_directory_win(name,
|
||||
changes = {name: {'directory': 'new'}}
|
||||
else:
|
||||
# Check owner
|
||||
if win_owner is not None:
|
||||
owner = salt.utils.win_dacl.get_owner(name)
|
||||
if not owner.lower() == win_owner.lower():
|
||||
changes['owner'] = win_owner
|
||||
@ -930,33 +931,46 @@ def _check_touch(name, atime, mtime):
|
||||
|
||||
|
||||
def _get_symlink_ownership(path):
|
||||
if salt.utils.is_windows():
|
||||
owner = salt.utils.win_dacl.get_owner(path)
|
||||
return owner, owner
|
||||
else:
|
||||
return (
|
||||
__salt__['file.get_user'](path, follow_symlinks=False),
|
||||
__salt__['file.get_group'](path, follow_symlinks=False)
|
||||
)
|
||||
|
||||
|
||||
def _check_symlink_ownership(path, user, group):
|
||||
def _check_symlink_ownership(path, user, group, win_owner):
|
||||
'''
|
||||
Check if the symlink ownership matches the specified user and group
|
||||
'''
|
||||
cur_user, cur_group = _get_symlink_ownership(path)
|
||||
if salt.utils.is_windows():
|
||||
return win_owner == cur_user
|
||||
else:
|
||||
return (cur_user == user) and (cur_group == group)
|
||||
|
||||
|
||||
def _set_symlink_ownership(path, user, group):
|
||||
def _set_symlink_ownership(path, user, group, win_owner):
|
||||
'''
|
||||
Set the ownership of a symlink and return a boolean indicating
|
||||
success/failure
|
||||
'''
|
||||
if salt.utils.is_windows():
|
||||
try:
|
||||
salt.utils.win_dacl.set_owner(path, win_owner)
|
||||
except CommandExecutionError:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
__salt__['file.lchown'](path, user, group)
|
||||
except OSError:
|
||||
pass
|
||||
return _check_symlink_ownership(path, user, group)
|
||||
return _check_symlink_ownership(path, user, group, win_owner)
|
||||
|
||||
|
||||
def _symlink_check(name, target, force, user, group):
|
||||
def _symlink_check(name, target, force, user, group, win_owner):
|
||||
'''
|
||||
Check the symlink function
|
||||
'''
|
||||
@ -975,7 +989,7 @@ def _symlink_check(name, target, force, user, group):
|
||||
else:
|
||||
result = True
|
||||
msg = 'The symlink {0} is present'.format(name)
|
||||
if not _check_symlink_ownership(name, user, group):
|
||||
if not _check_symlink_ownership(name, user, group, win_owner):
|
||||
result = None
|
||||
pchanges['ownership'] = '{0}:{1}'.format(*_get_symlink_ownership(name))
|
||||
msg += (
|
||||
@ -1199,6 +1213,57 @@ def _shortcut_check(name,
|
||||
'should be. Did you mean to use force?'.format(name)), pchanges
|
||||
|
||||
|
||||
def _makedirs(name,
|
||||
user=None,
|
||||
group=None,
|
||||
dir_mode=None,
|
||||
win_owner=None,
|
||||
win_perms=None,
|
||||
win_deny_perms=None,
|
||||
win_inheritance=None):
|
||||
'''
|
||||
Helper function for creating directories when the ``makedirs`` option is set
|
||||
to ``True``. Handles Unix and Windows based systems
|
||||
|
||||
.. versionadded:: 2017.7.7
|
||||
|
||||
Args:
|
||||
name (str): The directory path to create
|
||||
user (str): The linux user to own the directory
|
||||
group (str): The linux group to own the directory
|
||||
dir_mode (str): The linux mode to apply to the directory
|
||||
win_owner (str): The Windows user to own the directory
|
||||
win_perms (dict): A dictionary of grant permissions for Windows
|
||||
win_deny_perms (dict): A dictionary of deny permissions for Windows
|
||||
win_inheritance (bool): True to inherit permissions on Windows
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False on Windows
|
||||
str: Error messages on failure on Linux
|
||||
None: On successful creation on Linux
|
||||
|
||||
Raises:
|
||||
CommandExecutionError: If the drive is not mounted on Windows
|
||||
'''
|
||||
if salt.utils.is_windows():
|
||||
# Make sure the drive is mapped before trying to create the
|
||||
# path in windows
|
||||
drive, path = os.path.splitdrive(name)
|
||||
if not os.path.isdir(drive):
|
||||
raise CommandExecutionError(drive)
|
||||
win_owner = win_owner if win_owner else user
|
||||
return __salt__['file.makedirs'](path=name,
|
||||
owner=win_owner,
|
||||
grant_perms=win_perms,
|
||||
deny_perms=win_deny_perms,
|
||||
inheritance=win_inheritance)
|
||||
else:
|
||||
return __salt__['file.makedirs'](path=name,
|
||||
user=user,
|
||||
group=group,
|
||||
mode=dir_mode)
|
||||
|
||||
|
||||
def symlink(
|
||||
name,
|
||||
target,
|
||||
@ -1208,6 +1273,10 @@ def symlink(
|
||||
user=None,
|
||||
group=None,
|
||||
mode=None,
|
||||
win_owner=None,
|
||||
win_perms=None,
|
||||
win_deny_perms=None,
|
||||
win_inheritance=None,
|
||||
**kwargs):
|
||||
'''
|
||||
Create a symbolic link (symlink, soft link)
|
||||
@ -1256,6 +1325,28 @@ def symlink(
|
||||
|
||||
The default mode for new files and directories corresponds umask of salt
|
||||
process. For existing files and directories it's not enforced.
|
||||
|
||||
win_owner : None
|
||||
The owner of the symlink and directories if ``makedirs`` is True. If
|
||||
this is not passed, ``user`` will be used. If ``user`` is not passed,
|
||||
the account under which Salt is running will be used.
|
||||
|
||||
.. versionadded:: 2017.7.7
|
||||
|
||||
win_perms : None
|
||||
A dictionary containing permissions to grant
|
||||
|
||||
.. versionadded:: 2017.7.7
|
||||
|
||||
win_deny_perms : None
|
||||
A dictionary containing permissions to deny
|
||||
|
||||
.. versionadded:: 2017.7.7
|
||||
|
||||
win_inheritance : None
|
||||
True to inherit permissions from parent, otherwise False
|
||||
|
||||
.. versionadded:: 2017.7.7
|
||||
'''
|
||||
name = os.path.expanduser(name)
|
||||
|
||||
@ -1284,10 +1375,16 @@ def symlink(
|
||||
if not user:
|
||||
user = 'SYSTEM'
|
||||
|
||||
# If win_owner is not passed, use user
|
||||
if win_owner is None:
|
||||
win_owner = user if user else None
|
||||
|
||||
# Group isn't relevant to Windows, use win_perms/win_deny_perms
|
||||
if group is not None:
|
||||
log.warning(
|
||||
'The group argument for {0} has been ignored as this '
|
||||
'is a Windows system.'.format(name)
|
||||
'is a Windows system. Please use the `win_*` parameters to set '
|
||||
'permissions in Windows.'.format(name)
|
||||
)
|
||||
group = user
|
||||
|
||||
@ -1297,6 +1394,23 @@ def symlink(
|
||||
)
|
||||
|
||||
preflight_errors = []
|
||||
if salt.utils.is_windows():
|
||||
# Make sure the passed owner exists
|
||||
if not salt.utils.win_functions.get_sid_from_name(win_owner):
|
||||
preflight_errors.append('User {0} does not exist'.format(win_owner))
|
||||
|
||||
# Make sure users passed in win_perms exist
|
||||
if win_perms:
|
||||
for name_check in win_perms:
|
||||
if not salt.utils.win_functions.get_sid_from_name(name_check):
|
||||
preflight_errors.append('User {0} does not exist'.format(name_check))
|
||||
|
||||
# Make sure users passed in win_deny_perms exist
|
||||
if win_deny_perms:
|
||||
for name_check in win_deny_perms:
|
||||
if not salt.utils.win_functions.get_sid_from_name(name_check):
|
||||
preflight_errors.append('User {0} does not exist'.format(name_check))
|
||||
else:
|
||||
uid = __salt__['file.user_to_uid'](user)
|
||||
gid = __salt__['file.group_to_gid'](group)
|
||||
|
||||
@ -1321,19 +1435,29 @@ def symlink(
|
||||
target,
|
||||
force,
|
||||
user,
|
||||
group)
|
||||
if __opts__['test']:
|
||||
ret['result'] = presult
|
||||
ret['comment'] = pcomment
|
||||
return ret
|
||||
group,
|
||||
win_owner)
|
||||
|
||||
if not os.path.isdir(os.path.dirname(name)):
|
||||
if makedirs:
|
||||
__salt__['file.makedirs'](
|
||||
name,
|
||||
if __opts__['test']:
|
||||
pcomment += '\n{0} will be created'.format(os.path.dirname(name))
|
||||
else:
|
||||
try:
|
||||
_makedirs(name=name,
|
||||
user=user,
|
||||
group=group,
|
||||
mode=mode)
|
||||
dir_mode=mode,
|
||||
win_owner=win_owner,
|
||||
win_perms=win_perms,
|
||||
win_deny_perms=win_deny_perms,
|
||||
win_inheritance=win_inheritance)
|
||||
except CommandExecutionError as exc:
|
||||
return _error(ret, 'Drive {0} is not mapped'.format(exc.message))
|
||||
else:
|
||||
if __opts__['test']:
|
||||
pcomment += '\nDirectory {0} for symlink is not present' \
|
||||
''.format(os.path.dirname(name))
|
||||
else:
|
||||
return _error(
|
||||
ret,
|
||||
@ -1341,27 +1465,47 @@ def symlink(
|
||||
os.path.dirname(name)
|
||||
)
|
||||
)
|
||||
|
||||
if __opts__['test']:
|
||||
ret['result'] = presult
|
||||
ret['comment'] = pcomment
|
||||
return ret
|
||||
|
||||
if __salt__['file.is_link'](name):
|
||||
# The link exists, verify that it matches the target
|
||||
if os.path.normpath(__salt__['file.readlink'](name)) != os.path.normpath(target):
|
||||
# The target is wrong, delete the link
|
||||
os.remove(name)
|
||||
else:
|
||||
if _check_symlink_ownership(name, user, group):
|
||||
if _check_symlink_ownership(name, user, group, win_owner):
|
||||
# The link looks good!
|
||||
if salt.utils.is_windows():
|
||||
ret['comment'] = ('Symlink {0} is present and owned by {1}'
|
||||
''.format(name, win_owner))
|
||||
else:
|
||||
ret['comment'] = ('Symlink {0} is present and owned by '
|
||||
'{1}:{2}'.format(name, user, group))
|
||||
else:
|
||||
if _set_symlink_ownership(name, user, group):
|
||||
if _set_symlink_ownership(name, user, group, win_owner):
|
||||
if salt.utils.is_windows():
|
||||
ret['comment'] = ('Set ownership of symlink {0} to '
|
||||
'{1}'.format(name, win_owner))
|
||||
ret['changes']['ownership'] = win_owner
|
||||
else:
|
||||
ret['comment'] = ('Set ownership of symlink {0} to '
|
||||
'{1}:{2}'.format(name, user, group))
|
||||
ret['changes']['ownership'] = '{0}:{1}'.format(user, group)
|
||||
ret['changes']['ownership'] = '{0}:{1}'.format(user,
|
||||
group)
|
||||
else:
|
||||
ret['result'] = False
|
||||
if salt.utils.is_windows():
|
||||
ret['comment'] += (
|
||||
'Failed to set ownership of symlink '
|
||||
'{0} to {1}'.format(name, win_owner))
|
||||
else:
|
||||
ret['comment'] += (
|
||||
'Failed to set ownership of symlink {0} to '
|
||||
'{1}:{2}'.format(name, user, group)
|
||||
)
|
||||
'{1}:{2}'.format(name, user, group))
|
||||
return ret
|
||||
|
||||
elif os.path.isfile(name) or os.path.isdir(name):
|
||||
@ -1408,8 +1552,8 @@ def symlink(
|
||||
'{1}'.format(name, target))
|
||||
ret['changes']['new'] = name
|
||||
|
||||
if not _check_symlink_ownership(name, user, group):
|
||||
if not _set_symlink_ownership(name, user, group):
|
||||
if not _check_symlink_ownership(name, user, group, win_owner):
|
||||
if not _set_symlink_ownership(name, user, group, win_owner):
|
||||
ret['result'] = False
|
||||
ret['comment'] += (', but was unable to set ownership to '
|
||||
'{0}:{1}'.format(user, group))
|
||||
@ -2881,18 +3025,17 @@ def directory(name,
|
||||
# The parent directory does not exist, create them
|
||||
if makedirs:
|
||||
# Everything's good, create the parent Dirs
|
||||
if salt.utils.is_windows():
|
||||
# Make sure the drive is mapped before trying to create the
|
||||
# path in windows
|
||||
drive, path = os.path.splitdrive(name)
|
||||
if not os.path.isdir(drive):
|
||||
return _error(
|
||||
ret, 'Drive {0} is not mapped'.format(drive))
|
||||
__salt__['file.makedirs'](name, win_owner, win_perms,
|
||||
win_deny_perms, win_inheritance)
|
||||
else:
|
||||
__salt__['file.makedirs'](name, user=user, group=group,
|
||||
mode=dir_mode)
|
||||
try:
|
||||
_makedirs(name=name,
|
||||
user=user,
|
||||
group=group,
|
||||
dir_mode=dir_mode,
|
||||
win_owner=win_owner,
|
||||
win_perms=win_perms,
|
||||
win_deny_perms=win_deny_perms,
|
||||
win_inheritance=win_inheritance)
|
||||
except CommandExecutionError as exc:
|
||||
return _error(ret, 'Drive {0} is not mapped'.format(exc.message))
|
||||
else:
|
||||
return _error(
|
||||
ret, 'No directory to create {0} in'.format(name))
|
||||
@ -3064,6 +3207,10 @@ def recurse(name,
|
||||
maxdepth=None,
|
||||
keep_symlinks=False,
|
||||
force_symlinks=False,
|
||||
win_owner=None,
|
||||
win_perms=None,
|
||||
win_deny_perms=None,
|
||||
win_inheritance=True,
|
||||
**kwargs):
|
||||
'''
|
||||
Recurse through a subdirectory on the master and copy said subdirectory
|
||||
@ -3218,6 +3365,28 @@ def recurse(name,
|
||||
If a file or directory is obstructing symlink creation it will be
|
||||
recursively removed so that symlink creation can proceed. This
|
||||
option is usually not needed except in special circumstances.
|
||||
|
||||
win_owner : None
|
||||
The owner of the symlink and directories if ``makedirs`` is True. If
|
||||
this is not passed, ``user`` will be used. If ``user`` is not passed,
|
||||
the account under which Salt is running will be used.
|
||||
|
||||
.. versionadded:: 2017.7.7
|
||||
|
||||
win_perms : None
|
||||
A dictionary containing permissions to grant
|
||||
|
||||
.. versionadded:: 2017.7.7
|
||||
|
||||
win_deny_perms : None
|
||||
A dictionary containing permissions to deny
|
||||
|
||||
.. versionadded:: 2017.7.7
|
||||
|
||||
win_inheritance : None
|
||||
True to inherit permissions from parent, otherwise False
|
||||
|
||||
.. versionadded:: 2017.7.7
|
||||
'''
|
||||
if 'env' in kwargs:
|
||||
salt.utils.warn_until(
|
||||
@ -3321,7 +3490,18 @@ def recurse(name,
|
||||
return _error(
|
||||
ret, 'The path {0} exists and is not a directory'.format(name))
|
||||
if not __opts__['test']:
|
||||
__salt__['file.makedirs_perms'](name, user, group, dir_mode)
|
||||
if salt.utils.is_windows():
|
||||
win_owner = win_owner if win_owner else user
|
||||
__salt__['file.makedirs_perms'](path=name,
|
||||
owner=win_owner,
|
||||
grant_perms=win_perms,
|
||||
deny_perms=win_deny_perms,
|
||||
inheritance=win_inheritance)
|
||||
else:
|
||||
__salt__['file.makedirs_perms'](name=name,
|
||||
user=user,
|
||||
group=group,
|
||||
mode=dir_mode)
|
||||
|
||||
def add_comment(path, comment):
|
||||
comments = ret['comment'].setdefault(path, [])
|
||||
@ -4701,10 +4881,16 @@ def append(name,
|
||||
if makedirs is True:
|
||||
dirname = os.path.dirname(name)
|
||||
if not __salt__['file.directory_exists'](dirname):
|
||||
__salt__['file.makedirs'](name)
|
||||
check_res, check_msg, ret['pchanges'] = _check_directory(
|
||||
dirname, None, None, False, None, False, False, None
|
||||
)
|
||||
try:
|
||||
_makedirs(name=name)
|
||||
except CommandExecutionError as exc:
|
||||
return _error(ret, 'Drive {0} is not mapped'.format(exc.message))
|
||||
|
||||
if salt.utils.is_windows():
|
||||
check_res, check_msg, ret['pchanges'] = _check_directory_win(dirname)
|
||||
else:
|
||||
check_res, check_msg, ret['pchanges'] = _check_directory(dirname)
|
||||
|
||||
if not check_res:
|
||||
return _error(ret, check_msg)
|
||||
|
||||
@ -4815,6 +5001,90 @@ def prepend(name,
|
||||
The text will not be prepended again if it already exists in the file. You
|
||||
may specify a single line of text or a list of lines to append.
|
||||
|
||||
name
|
||||
The location of the file to append to.
|
||||
|
||||
text
|
||||
The text to be appended, which can be a single string or a list
|
||||
of strings.
|
||||
|
||||
makedirs
|
||||
If the file is located in a path without a parent directory,
|
||||
then the state will fail. If makedirs is set to True, then
|
||||
the parent directories will be created to facilitate the
|
||||
creation of the named file. Defaults to False.
|
||||
|
||||
source
|
||||
A single source file to append. This source file can be hosted on either
|
||||
the salt master server, or on an HTTP or FTP server. Both HTTPS and
|
||||
HTTP are supported as well as downloading directly from Amazon S3
|
||||
compatible URLs with both pre-configured and automatic IAM credentials
|
||||
(see s3.get state documentation). File retrieval from Openstack Swift
|
||||
object storage is supported via swift://container/object_path URLs
|
||||
(see swift.get documentation).
|
||||
|
||||
For files hosted on the salt file server, if the file is located on
|
||||
the master in the directory named spam, and is called eggs, the source
|
||||
string is salt://spam/eggs.
|
||||
|
||||
If the file is hosted on an HTTP or FTP server, the source_hash argument
|
||||
is also required.
|
||||
|
||||
source_hash
|
||||
This can be one of the following:
|
||||
1. a source hash string
|
||||
2. the URI of a file that contains source hash strings
|
||||
|
||||
The function accepts the first encountered long unbroken alphanumeric
|
||||
string of correct length as a valid hash, in order from most secure to
|
||||
least secure:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Type Length
|
||||
====== ======
|
||||
sha512 128
|
||||
sha384 96
|
||||
sha256 64
|
||||
sha224 56
|
||||
sha1 40
|
||||
md5 32
|
||||
|
||||
See the ``source_hash`` parameter description for :mod:`file.managed
|
||||
<salt.states.file.managed>` function for more details and examples.
|
||||
|
||||
template
|
||||
The named templating engine will be used to render the appended-to file.
|
||||
Defaults to ``jinja``. The following templates are supported:
|
||||
|
||||
- :mod:`cheetah<salt.renderers.cheetah>`
|
||||
- :mod:`genshi<salt.renderers.genshi>`
|
||||
- :mod:`jinja<salt.renderers.jinja>`
|
||||
- :mod:`mako<salt.renderers.mako>`
|
||||
- :mod:`py<salt.renderers.py>`
|
||||
- :mod:`wempy<salt.renderers.wempy>`
|
||||
|
||||
sources
|
||||
A list of source files to append. If the files are hosted on an HTTP or
|
||||
FTP server, the source_hashes argument is also required.
|
||||
|
||||
source_hashes
|
||||
A list of source_hashes corresponding to the sources list specified in
|
||||
the sources argument.
|
||||
|
||||
defaults
|
||||
Default context passed to the template.
|
||||
|
||||
context
|
||||
Overrides default context variables passed to the template.
|
||||
|
||||
ignore_whitespace
|
||||
.. versionadded:: 2015.8.4
|
||||
|
||||
Spaces and Tabs in text are ignored by default, when searching for the
|
||||
appending content, one space or multiple tabs are the same for salt.
|
||||
Set this option to ``False`` if you want to change this behavior.
|
||||
|
||||
Multi-line example:
|
||||
|
||||
.. code-block:: yaml
|
||||
@ -4893,10 +5163,15 @@ def prepend(name,
|
||||
if makedirs is True:
|
||||
dirname = os.path.dirname(name)
|
||||
if not __salt__['file.directory_exists'](dirname):
|
||||
__salt__['file.makedirs'](name)
|
||||
check_res, check_msg, ret['pchanges'] = _check_directory(
|
||||
dirname, None, None, False, None, False, False, None
|
||||
)
|
||||
try:
|
||||
_makedirs(name=name)
|
||||
except CommandExecutionError as exc:
|
||||
return _error(ret, 'Drive {0} is not mapped'.format(exc.message))
|
||||
|
||||
if salt.utils.is_windows():
|
||||
check_res, check_msg, ret['pchanges'] = _check_directory_win(dirname)
|
||||
else:
|
||||
check_res, check_msg, ret['pchanges'] = _check_directory(dirname)
|
||||
if not check_res:
|
||||
return _error(ret, check_msg)
|
||||
|
||||
@ -5187,7 +5462,10 @@ def touch(name, atime=None, mtime=None, makedirs=False):
|
||||
return ret
|
||||
|
||||
if makedirs:
|
||||
__salt__['file.makedirs'](name)
|
||||
try:
|
||||
_makedirs(name=name)
|
||||
except CommandExecutionError as exc:
|
||||
return _error(ret, 'Drive {0} is not mapped'.format(exc.message))
|
||||
if not os.path.isdir(os.path.dirname(name)):
|
||||
return _error(
|
||||
ret, 'Directory not present to touch file {0}'.format(name)
|
||||
@ -5384,7 +5662,10 @@ def copy(
|
||||
dname = os.path.dirname(name)
|
||||
if not os.path.isdir(dname):
|
||||
if makedirs:
|
||||
__salt__['file.makedirs'](name)
|
||||
try:
|
||||
_makedirs(name=name)
|
||||
except CommandExecutionError as exc:
|
||||
return _error(ret, 'Drive {0} is not mapped'.format(exc.message))
|
||||
else:
|
||||
return _error(
|
||||
ret,
|
||||
@ -5481,7 +5762,10 @@ def rename(name, source, force=False, makedirs=False):
|
||||
dname = os.path.dirname(name)
|
||||
if not os.path.isdir(dname):
|
||||
if makedirs:
|
||||
__salt__['file.makedirs'](name)
|
||||
try:
|
||||
_makedirs(name=name)
|
||||
except CommandExecutionError as exc:
|
||||
return _error(ret, 'Drive {0} is not mapped'.format(exc.message))
|
||||
else:
|
||||
return _error(
|
||||
ret,
|
||||
@ -6377,9 +6661,10 @@ def shortcut(
|
||||
|
||||
if not os.path.isdir(os.path.dirname(name)):
|
||||
if makedirs:
|
||||
__salt__['file.makedirs'](
|
||||
name,
|
||||
user=user)
|
||||
try:
|
||||
_makedirs(name=name, user=user)
|
||||
except CommandExecutionError as exc:
|
||||
return _error(ret, 'Drive {0} is not mapped'.format(exc.message))
|
||||
else:
|
||||
return _error(
|
||||
ret,
|
||||
@ -6402,7 +6687,10 @@ def shortcut(
|
||||
time.sleep(1) # wait for asynchronous deletion
|
||||
if not os.path.isdir(os.path.dirname(backupname)):
|
||||
if makedirs:
|
||||
os.makedirs(backupname)
|
||||
try:
|
||||
_makedirs(name=backupname)
|
||||
except CommandExecutionError as exc:
|
||||
return _error(ret, 'Drive {0} is not mapped'.format(exc.message))
|
||||
else:
|
||||
return _error(ret, (
|
||||
'Directory does not exist for'
|
||||
|
Loading…
Reference in New Issue
Block a user