diff --git a/src/SPC/builder/extension/pdo_sqlsrv.php b/src/SPC/builder/extension/pdo_sqlsrv.php new file mode 100644 index 00000000..32697b16 --- /dev/null +++ b/src/SPC/builder/extension/pdo_sqlsrv.php @@ -0,0 +1,26 @@ +source_dir . '/config.m4') && is_dir($this->source_dir . '/source/pdo_sqlsrv')) { + FileSystem::moveFileOrDir($this->source_dir . '/LICENSE', $this->source_dir . '/source/pdo_sqlsrv/LICENSE'); + FileSystem::moveFileOrDir($this->source_dir . '/source/shared', $this->source_dir . '/source/pdo_sqlsrv/shared'); + FileSystem::moveFileOrDir($this->source_dir . '/source/pdo_sqlsrv', SOURCE_PATH . '/pdo_sqlsrv'); + FileSystem::removeDir($this->source_dir); + FileSystem::moveFileOrDir(SOURCE_PATH . '/pdo_sqlsrv', $this->source_dir); + return true; + } + return false; + } +} diff --git a/src/SPC/store/FileSystem.php b/src/SPC/store/FileSystem.php index 3b88a2bc..f6c538bd 100644 --- a/src/SPC/store/FileSystem.php +++ b/src/SPC/store/FileSystem.php @@ -572,6 +572,44 @@ class FileSystem return file_put_contents($file, implode('', $lines)); } + /** + * Move file or directory, handling cross-device scenarios + * Uses rename() if possible, falls back to copy+delete for cross-device moves + * + * @param string $source Source path + * @param string $dest Destination path + */ + public static function moveFileOrDir(string $source, string $dest): void + { + $source = self::convertPath($source); + $dest = self::convertPath($dest); + + // Check if source and dest are on the same device to avoid cross-device rename errors + $source_stat = @stat($source); + $dest_parent = dirname($dest); + $dest_stat = @stat($dest_parent); + + // Only use rename if on same device + if ($source_stat !== false && $dest_stat !== false && $source_stat['dev'] === $dest_stat['dev']) { + if (@rename($source, $dest)) { + return; + } + } + + // Fall back to copy + delete for cross-device moves or if rename failed + if (is_dir($source)) { + self::copyDir($source, $dest); + self::removeDir($source); + } else { + if (!copy($source, $dest)) { + throw new FileSystemException("Failed to copy file from {$source} to {$dest}"); + } + if (!unlink($source)) { + throw new FileSystemException("Failed to remove source file: {$source}"); + } + } + } + private static function extractArchive(string $filename, string $target): void { // Create base dir @@ -648,44 +686,6 @@ class FileSystem }; } - /** - * Move file or directory, handling cross-device scenarios - * Uses rename() if possible, falls back to copy+delete for cross-device moves - * - * @param string $source Source path - * @param string $dest Destination path - */ - private static function moveFileOrDir(string $source, string $dest): void - { - $source = self::convertPath($source); - $dest = self::convertPath($dest); - - // Check if source and dest are on the same device to avoid cross-device rename errors - $source_stat = @stat($source); - $dest_parent = dirname($dest); - $dest_stat = @stat($dest_parent); - - // Only use rename if on same device - if ($source_stat !== false && $dest_stat !== false && $source_stat['dev'] === $dest_stat['dev']) { - if (@rename($source, $dest)) { - return; - } - } - - // Fall back to copy + delete for cross-device moves or if rename failed - if (is_dir($source)) { - self::copyDir($source, $dest); - self::removeDir($source); - } else { - if (!copy($source, $dest)) { - throw new FileSystemException("Failed to copy file from {$source} to {$dest}"); - } - if (!unlink($source)) { - throw new FileSystemException("Failed to remove source file: {$source}"); - } - } - } - /** * Unzip file with stripping top-level directory */