fix(files_external): on case insensitive system, block case change

When a file/directory is renamed to the same name with only case change,
the rename fail. We block this kind of rename.
The user will have to rename to another name first.

Signed-off-by: Benjamin Gaussorgues <benjamin.gaussorgues@nextcloud.com>
pull/41053/head
Benjamin Gaussorgues 2023-10-23 10:15:46 +07:00
parent 61143644a4
commit a45e12abc8
No known key found for this signature in database
GPG Key ID: 5DAC1CAFAA6DB883
2 changed files with 24 additions and 0 deletions

@ -59,6 +59,11 @@ class SMB extends Backend {
(new DefinitionParameter('show_hidden', $l->t('Show hidden files')))
->setType(DefinitionParameter::VALUE_BOOLEAN)
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
(new DefinitionParameter('case_sensitive', $l->t('Case sensitive file system')))
->setType(DefinitionParameter::VALUE_BOOLEAN)
->setFlag(DefinitionParameter::FLAG_OPTIONAL)
->setDefaultValue(true)
->setTooltip($l->t('Disabling it will allow to use a case insentive file system, but comes with a performance penalty')),
(new DefinitionParameter('check_acl', $l->t('Verify ACL access when listing files')))
->setType(DefinitionParameter::VALUE_BOOLEAN)
->setFlag(DefinitionParameter::FLAG_OPTIONAL)

@ -93,6 +93,8 @@ class SMB extends Common implements INotifyStorage {
/** @var bool */
protected $showHidden;
private bool $caseSensitive;
/** @var bool */
protected $checkAcl;
@ -139,6 +141,7 @@ class SMB extends Common implements INotifyStorage {
$this->root = rtrim($this->root, '/') . '/';
$this->showHidden = isset($params['show_hidden']) && $params['show_hidden'];
$this->caseSensitive = (bool) ($params['case_sensitive'] ?? true);
$this->checkAcl = isset($params['check_acl']) && $params['check_acl'];
$this->statCache = new CappedMemoryCache();
@ -325,6 +328,12 @@ class SMB extends Common implements INotifyStorage {
if ($this->isRootDir($source) || $this->isRootDir($target)) {
return false;
}
if ($this->caseSensitive === false
&& mb_strtolower($target) === mb_strtolower($source)
) {
// Forbid changing case only on case-insensitive file system
return false;
}
$absoluteSource = $this->buildPath($source);
$absoluteTarget = $this->buildPath($target);
@ -674,6 +683,16 @@ class SMB extends Common implements INotifyStorage {
public function file_exists($path) {
try {
if ($this->caseSensitive === false) {
$filename = basename($path);
$siblings = $this->getDirectoryContent(dirname($this->buildPath($path)));
foreach ($siblings as $sibling) {
if ($sibling['name'] === $filename) {
return true;
}
}
return false;
}
$this->getFileInfo($path);
return true;
} catch (\OCP\Files\NotFoundException $e) {