11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ci// This file is a modified version of the fs-extra's copySync method. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciconst { areIdentical, isSrcSubdir } = require('internal/fs/cp/cp'); 61cb0ef41Sopenharmony_ciconst { codes } = require('internal/errors'); 71cb0ef41Sopenharmony_ciconst { 81cb0ef41Sopenharmony_ci os: { 91cb0ef41Sopenharmony_ci errno: { 101cb0ef41Sopenharmony_ci EEXIST, 111cb0ef41Sopenharmony_ci EISDIR, 121cb0ef41Sopenharmony_ci EINVAL, 131cb0ef41Sopenharmony_ci ENOTDIR, 141cb0ef41Sopenharmony_ci }, 151cb0ef41Sopenharmony_ci }, 161cb0ef41Sopenharmony_ci} = internalBinding('constants'); 171cb0ef41Sopenharmony_ciconst { 181cb0ef41Sopenharmony_ci ERR_FS_CP_DIR_TO_NON_DIR, 191cb0ef41Sopenharmony_ci ERR_FS_CP_EEXIST, 201cb0ef41Sopenharmony_ci ERR_FS_CP_EINVAL, 211cb0ef41Sopenharmony_ci ERR_FS_CP_FIFO_PIPE, 221cb0ef41Sopenharmony_ci ERR_FS_CP_NON_DIR_TO_DIR, 231cb0ef41Sopenharmony_ci ERR_FS_CP_SOCKET, 241cb0ef41Sopenharmony_ci ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY, 251cb0ef41Sopenharmony_ci ERR_FS_CP_UNKNOWN, 261cb0ef41Sopenharmony_ci ERR_FS_EISDIR, 271cb0ef41Sopenharmony_ci ERR_INVALID_RETURN_VALUE, 281cb0ef41Sopenharmony_ci} = codes; 291cb0ef41Sopenharmony_ciconst { 301cb0ef41Sopenharmony_ci chmodSync, 311cb0ef41Sopenharmony_ci copyFileSync, 321cb0ef41Sopenharmony_ci existsSync, 331cb0ef41Sopenharmony_ci lstatSync, 341cb0ef41Sopenharmony_ci mkdirSync, 351cb0ef41Sopenharmony_ci opendirSync, 361cb0ef41Sopenharmony_ci readlinkSync, 371cb0ef41Sopenharmony_ci statSync, 381cb0ef41Sopenharmony_ci symlinkSync, 391cb0ef41Sopenharmony_ci unlinkSync, 401cb0ef41Sopenharmony_ci utimesSync, 411cb0ef41Sopenharmony_ci} = require('fs'); 421cb0ef41Sopenharmony_ciconst { 431cb0ef41Sopenharmony_ci dirname, 441cb0ef41Sopenharmony_ci isAbsolute, 451cb0ef41Sopenharmony_ci join, 461cb0ef41Sopenharmony_ci parse, 471cb0ef41Sopenharmony_ci resolve, 481cb0ef41Sopenharmony_ci} = require('path'); 491cb0ef41Sopenharmony_ciconst { isPromise } = require('util/types'); 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_cifunction cpSyncFn(src, dest, opts) { 521cb0ef41Sopenharmony_ci // Warn about using preserveTimestamps on 32-bit node 531cb0ef41Sopenharmony_ci if (opts.preserveTimestamps && process.arch === 'ia32') { 541cb0ef41Sopenharmony_ci const warning = 'Using the preserveTimestamps option in 32-bit ' + 551cb0ef41Sopenharmony_ci 'node is not recommended'; 561cb0ef41Sopenharmony_ci process.emitWarning(warning, 'TimestampPrecisionWarning'); 571cb0ef41Sopenharmony_ci } 581cb0ef41Sopenharmony_ci const { srcStat, destStat, skipped } = checkPathsSync(src, dest, opts); 591cb0ef41Sopenharmony_ci if (skipped) return; 601cb0ef41Sopenharmony_ci checkParentPathsSync(src, srcStat, dest); 611cb0ef41Sopenharmony_ci return checkParentDir(destStat, src, dest, opts); 621cb0ef41Sopenharmony_ci} 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_cifunction checkPathsSync(src, dest, opts) { 651cb0ef41Sopenharmony_ci if (opts.filter) { 661cb0ef41Sopenharmony_ci const shouldCopy = opts.filter(src, dest); 671cb0ef41Sopenharmony_ci if (isPromise(shouldCopy)) { 681cb0ef41Sopenharmony_ci throw new ERR_INVALID_RETURN_VALUE('boolean', 'filter', shouldCopy); 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci if (!shouldCopy) return { __proto__: null, skipped: true }; 711cb0ef41Sopenharmony_ci } 721cb0ef41Sopenharmony_ci const { srcStat, destStat } = getStatsSync(src, dest, opts); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci if (destStat) { 751cb0ef41Sopenharmony_ci if (areIdentical(srcStat, destStat)) { 761cb0ef41Sopenharmony_ci throw new ERR_FS_CP_EINVAL({ 771cb0ef41Sopenharmony_ci message: 'src and dest cannot be the same', 781cb0ef41Sopenharmony_ci path: dest, 791cb0ef41Sopenharmony_ci syscall: 'cp', 801cb0ef41Sopenharmony_ci errno: EINVAL, 811cb0ef41Sopenharmony_ci code: 'EINVAL', 821cb0ef41Sopenharmony_ci }); 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci if (srcStat.isDirectory() && !destStat.isDirectory()) { 851cb0ef41Sopenharmony_ci throw new ERR_FS_CP_DIR_TO_NON_DIR({ 861cb0ef41Sopenharmony_ci message: `cannot overwrite directory ${src} ` + 871cb0ef41Sopenharmony_ci `with non-directory ${dest}`, 881cb0ef41Sopenharmony_ci path: dest, 891cb0ef41Sopenharmony_ci syscall: 'cp', 901cb0ef41Sopenharmony_ci errno: EISDIR, 911cb0ef41Sopenharmony_ci code: 'EISDIR', 921cb0ef41Sopenharmony_ci }); 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci if (!srcStat.isDirectory() && destStat.isDirectory()) { 951cb0ef41Sopenharmony_ci throw new ERR_FS_CP_NON_DIR_TO_DIR({ 961cb0ef41Sopenharmony_ci message: `cannot overwrite non-directory ${src} ` + 971cb0ef41Sopenharmony_ci `with directory ${dest}`, 981cb0ef41Sopenharmony_ci path: dest, 991cb0ef41Sopenharmony_ci syscall: 'cp', 1001cb0ef41Sopenharmony_ci errno: ENOTDIR, 1011cb0ef41Sopenharmony_ci code: 'ENOTDIR', 1021cb0ef41Sopenharmony_ci }); 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci } 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci if (srcStat.isDirectory() && isSrcSubdir(src, dest)) { 1071cb0ef41Sopenharmony_ci throw new ERR_FS_CP_EINVAL({ 1081cb0ef41Sopenharmony_ci message: `cannot copy ${src} to a subdirectory of self ${dest}`, 1091cb0ef41Sopenharmony_ci path: dest, 1101cb0ef41Sopenharmony_ci syscall: 'cp', 1111cb0ef41Sopenharmony_ci errno: EINVAL, 1121cb0ef41Sopenharmony_ci code: 'EINVAL', 1131cb0ef41Sopenharmony_ci }); 1141cb0ef41Sopenharmony_ci } 1151cb0ef41Sopenharmony_ci return { __proto__: null, srcStat, destStat, skipped: false }; 1161cb0ef41Sopenharmony_ci} 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_cifunction getStatsSync(src, dest, opts) { 1191cb0ef41Sopenharmony_ci let destStat; 1201cb0ef41Sopenharmony_ci const statFunc = opts.dereference ? 1211cb0ef41Sopenharmony_ci (file) => statSync(file, { bigint: true }) : 1221cb0ef41Sopenharmony_ci (file) => lstatSync(file, { bigint: true }); 1231cb0ef41Sopenharmony_ci const srcStat = statFunc(src); 1241cb0ef41Sopenharmony_ci try { 1251cb0ef41Sopenharmony_ci destStat = statFunc(dest); 1261cb0ef41Sopenharmony_ci } catch (err) { 1271cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') return { srcStat, destStat: null }; 1281cb0ef41Sopenharmony_ci throw err; 1291cb0ef41Sopenharmony_ci } 1301cb0ef41Sopenharmony_ci return { srcStat, destStat }; 1311cb0ef41Sopenharmony_ci} 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_cifunction checkParentPathsSync(src, srcStat, dest) { 1341cb0ef41Sopenharmony_ci const srcParent = resolve(dirname(src)); 1351cb0ef41Sopenharmony_ci const destParent = resolve(dirname(dest)); 1361cb0ef41Sopenharmony_ci if (destParent === srcParent || destParent === parse(destParent).root) return; 1371cb0ef41Sopenharmony_ci let destStat; 1381cb0ef41Sopenharmony_ci try { 1391cb0ef41Sopenharmony_ci destStat = statSync(destParent, { bigint: true }); 1401cb0ef41Sopenharmony_ci } catch (err) { 1411cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') return; 1421cb0ef41Sopenharmony_ci throw err; 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci if (areIdentical(srcStat, destStat)) { 1451cb0ef41Sopenharmony_ci throw new ERR_FS_CP_EINVAL({ 1461cb0ef41Sopenharmony_ci message: `cannot copy ${src} to a subdirectory of self ${dest}`, 1471cb0ef41Sopenharmony_ci path: dest, 1481cb0ef41Sopenharmony_ci syscall: 'cp', 1491cb0ef41Sopenharmony_ci errno: EINVAL, 1501cb0ef41Sopenharmony_ci code: 'EINVAL', 1511cb0ef41Sopenharmony_ci }); 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci return checkParentPathsSync(src, srcStat, destParent); 1541cb0ef41Sopenharmony_ci} 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_cifunction checkParentDir(destStat, src, dest, opts) { 1571cb0ef41Sopenharmony_ci const destParent = dirname(dest); 1581cb0ef41Sopenharmony_ci if (!existsSync(destParent)) mkdirSync(destParent, { recursive: true }); 1591cb0ef41Sopenharmony_ci return getStats(destStat, src, dest, opts); 1601cb0ef41Sopenharmony_ci} 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_cifunction getStats(destStat, src, dest, opts) { 1631cb0ef41Sopenharmony_ci const statSyncFn = opts.dereference ? statSync : lstatSync; 1641cb0ef41Sopenharmony_ci const srcStat = statSyncFn(src); 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci if (srcStat.isDirectory() && opts.recursive) { 1671cb0ef41Sopenharmony_ci return onDir(srcStat, destStat, src, dest, opts); 1681cb0ef41Sopenharmony_ci } else if (srcStat.isDirectory()) { 1691cb0ef41Sopenharmony_ci throw new ERR_FS_EISDIR({ 1701cb0ef41Sopenharmony_ci message: `${src} is a directory (not copied)`, 1711cb0ef41Sopenharmony_ci path: src, 1721cb0ef41Sopenharmony_ci syscall: 'cp', 1731cb0ef41Sopenharmony_ci errno: EINVAL, 1741cb0ef41Sopenharmony_ci code: 'EISDIR', 1751cb0ef41Sopenharmony_ci }); 1761cb0ef41Sopenharmony_ci } else if (srcStat.isFile() || 1771cb0ef41Sopenharmony_ci srcStat.isCharacterDevice() || 1781cb0ef41Sopenharmony_ci srcStat.isBlockDevice()) { 1791cb0ef41Sopenharmony_ci return onFile(srcStat, destStat, src, dest, opts); 1801cb0ef41Sopenharmony_ci } else if (srcStat.isSymbolicLink()) { 1811cb0ef41Sopenharmony_ci return onLink(destStat, src, dest, opts); 1821cb0ef41Sopenharmony_ci } else if (srcStat.isSocket()) { 1831cb0ef41Sopenharmony_ci throw new ERR_FS_CP_SOCKET({ 1841cb0ef41Sopenharmony_ci message: `cannot copy a socket file: ${dest}`, 1851cb0ef41Sopenharmony_ci path: dest, 1861cb0ef41Sopenharmony_ci syscall: 'cp', 1871cb0ef41Sopenharmony_ci errno: EINVAL, 1881cb0ef41Sopenharmony_ci code: 'EINVAL', 1891cb0ef41Sopenharmony_ci }); 1901cb0ef41Sopenharmony_ci } else if (srcStat.isFIFO()) { 1911cb0ef41Sopenharmony_ci throw new ERR_FS_CP_FIFO_PIPE({ 1921cb0ef41Sopenharmony_ci message: `cannot copy a FIFO pipe: ${dest}`, 1931cb0ef41Sopenharmony_ci path: dest, 1941cb0ef41Sopenharmony_ci syscall: 'cp', 1951cb0ef41Sopenharmony_ci errno: EINVAL, 1961cb0ef41Sopenharmony_ci code: 'EINVAL', 1971cb0ef41Sopenharmony_ci }); 1981cb0ef41Sopenharmony_ci } 1991cb0ef41Sopenharmony_ci throw new ERR_FS_CP_UNKNOWN({ 2001cb0ef41Sopenharmony_ci message: `cannot copy an unknown file type: ${dest}`, 2011cb0ef41Sopenharmony_ci path: dest, 2021cb0ef41Sopenharmony_ci syscall: 'cp', 2031cb0ef41Sopenharmony_ci errno: EINVAL, 2041cb0ef41Sopenharmony_ci code: 'EINVAL', 2051cb0ef41Sopenharmony_ci }); 2061cb0ef41Sopenharmony_ci} 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_cifunction onFile(srcStat, destStat, src, dest, opts) { 2091cb0ef41Sopenharmony_ci if (!destStat) return copyFile(srcStat, src, dest, opts); 2101cb0ef41Sopenharmony_ci return mayCopyFile(srcStat, src, dest, opts); 2111cb0ef41Sopenharmony_ci} 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_cifunction mayCopyFile(srcStat, src, dest, opts) { 2141cb0ef41Sopenharmony_ci if (opts.force) { 2151cb0ef41Sopenharmony_ci unlinkSync(dest); 2161cb0ef41Sopenharmony_ci return copyFile(srcStat, src, dest, opts); 2171cb0ef41Sopenharmony_ci } else if (opts.errorOnExist) { 2181cb0ef41Sopenharmony_ci throw new ERR_FS_CP_EEXIST({ 2191cb0ef41Sopenharmony_ci message: `${dest} already exists`, 2201cb0ef41Sopenharmony_ci path: dest, 2211cb0ef41Sopenharmony_ci syscall: 'cp', 2221cb0ef41Sopenharmony_ci errno: EEXIST, 2231cb0ef41Sopenharmony_ci code: 'EEXIST', 2241cb0ef41Sopenharmony_ci }); 2251cb0ef41Sopenharmony_ci } 2261cb0ef41Sopenharmony_ci} 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_cifunction copyFile(srcStat, src, dest, opts) { 2291cb0ef41Sopenharmony_ci copyFileSync(src, dest, opts.mode); 2301cb0ef41Sopenharmony_ci if (opts.preserveTimestamps) handleTimestamps(srcStat.mode, src, dest); 2311cb0ef41Sopenharmony_ci return setDestMode(dest, srcStat.mode); 2321cb0ef41Sopenharmony_ci} 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_cifunction handleTimestamps(srcMode, src, dest) { 2351cb0ef41Sopenharmony_ci // Make sure the file is writable before setting the timestamp 2361cb0ef41Sopenharmony_ci // otherwise open fails with EPERM when invoked with 'r+' 2371cb0ef41Sopenharmony_ci // (through utimes call) 2381cb0ef41Sopenharmony_ci if (fileIsNotWritable(srcMode)) makeFileWritable(dest, srcMode); 2391cb0ef41Sopenharmony_ci return setDestTimestamps(src, dest); 2401cb0ef41Sopenharmony_ci} 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_cifunction fileIsNotWritable(srcMode) { 2431cb0ef41Sopenharmony_ci return (srcMode & 0o200) === 0; 2441cb0ef41Sopenharmony_ci} 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_cifunction makeFileWritable(dest, srcMode) { 2471cb0ef41Sopenharmony_ci return setDestMode(dest, srcMode | 0o200); 2481cb0ef41Sopenharmony_ci} 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_cifunction setDestMode(dest, srcMode) { 2511cb0ef41Sopenharmony_ci return chmodSync(dest, srcMode); 2521cb0ef41Sopenharmony_ci} 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_cifunction setDestTimestamps(src, dest) { 2551cb0ef41Sopenharmony_ci // The initial srcStat.atime cannot be trusted 2561cb0ef41Sopenharmony_ci // because it is modified by the read(2) system call 2571cb0ef41Sopenharmony_ci // (See https://nodejs.org/api/fs.html#fs_stat_time_values) 2581cb0ef41Sopenharmony_ci const updatedSrcStat = statSync(src); 2591cb0ef41Sopenharmony_ci return utimesSync(dest, updatedSrcStat.atime, updatedSrcStat.mtime); 2601cb0ef41Sopenharmony_ci} 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_cifunction onDir(srcStat, destStat, src, dest, opts) { 2631cb0ef41Sopenharmony_ci if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts); 2641cb0ef41Sopenharmony_ci return copyDir(src, dest, opts); 2651cb0ef41Sopenharmony_ci} 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_cifunction mkDirAndCopy(srcMode, src, dest, opts) { 2681cb0ef41Sopenharmony_ci mkdirSync(dest); 2691cb0ef41Sopenharmony_ci copyDir(src, dest, opts); 2701cb0ef41Sopenharmony_ci return setDestMode(dest, srcMode); 2711cb0ef41Sopenharmony_ci} 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_cifunction copyDir(src, dest, opts) { 2741cb0ef41Sopenharmony_ci const dir = opendirSync(src); 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci try { 2771cb0ef41Sopenharmony_ci let dirent; 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci while ((dirent = dir.readSync()) !== null) { 2801cb0ef41Sopenharmony_ci const { name } = dirent; 2811cb0ef41Sopenharmony_ci const srcItem = join(src, name); 2821cb0ef41Sopenharmony_ci const destItem = join(dest, name); 2831cb0ef41Sopenharmony_ci const { destStat, skipped } = checkPathsSync(srcItem, destItem, opts); 2841cb0ef41Sopenharmony_ci if (!skipped) getStats(destStat, srcItem, destItem, opts); 2851cb0ef41Sopenharmony_ci } 2861cb0ef41Sopenharmony_ci } finally { 2871cb0ef41Sopenharmony_ci dir.closeSync(); 2881cb0ef41Sopenharmony_ci } 2891cb0ef41Sopenharmony_ci} 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_cifunction onLink(destStat, src, dest, opts) { 2921cb0ef41Sopenharmony_ci let resolvedSrc = readlinkSync(src); 2931cb0ef41Sopenharmony_ci if (!opts.verbatimSymlinks && !isAbsolute(resolvedSrc)) { 2941cb0ef41Sopenharmony_ci resolvedSrc = resolve(dirname(src), resolvedSrc); 2951cb0ef41Sopenharmony_ci } 2961cb0ef41Sopenharmony_ci if (!destStat) { 2971cb0ef41Sopenharmony_ci return symlinkSync(resolvedSrc, dest); 2981cb0ef41Sopenharmony_ci } 2991cb0ef41Sopenharmony_ci let resolvedDest; 3001cb0ef41Sopenharmony_ci try { 3011cb0ef41Sopenharmony_ci resolvedDest = readlinkSync(dest); 3021cb0ef41Sopenharmony_ci } catch (err) { 3031cb0ef41Sopenharmony_ci // Dest exists and is a regular file or directory, 3041cb0ef41Sopenharmony_ci // Windows may throw UNKNOWN error. If dest already exists, 3051cb0ef41Sopenharmony_ci // fs throws error anyway, so no need to guard against it here. 3061cb0ef41Sopenharmony_ci if (err.code === 'EINVAL' || err.code === 'UNKNOWN') { 3071cb0ef41Sopenharmony_ci return symlinkSync(resolvedSrc, dest); 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci throw err; 3101cb0ef41Sopenharmony_ci } 3111cb0ef41Sopenharmony_ci if (!isAbsolute(resolvedDest)) { 3121cb0ef41Sopenharmony_ci resolvedDest = resolve(dirname(dest), resolvedDest); 3131cb0ef41Sopenharmony_ci } 3141cb0ef41Sopenharmony_ci if (isSrcSubdir(resolvedSrc, resolvedDest)) { 3151cb0ef41Sopenharmony_ci throw new ERR_FS_CP_EINVAL({ 3161cb0ef41Sopenharmony_ci message: `cannot copy ${resolvedSrc} to a subdirectory of self ` + 3171cb0ef41Sopenharmony_ci `${resolvedDest}`, 3181cb0ef41Sopenharmony_ci path: dest, 3191cb0ef41Sopenharmony_ci syscall: 'cp', 3201cb0ef41Sopenharmony_ci errno: EINVAL, 3211cb0ef41Sopenharmony_ci code: 'EINVAL', 3221cb0ef41Sopenharmony_ci }); 3231cb0ef41Sopenharmony_ci } 3241cb0ef41Sopenharmony_ci // Prevent copy if src is a subdir of dest since unlinking 3251cb0ef41Sopenharmony_ci // dest in this case would result in removing src contents 3261cb0ef41Sopenharmony_ci // and therefore a broken symlink would be created. 3271cb0ef41Sopenharmony_ci if (statSync(dest).isDirectory() && isSrcSubdir(resolvedDest, resolvedSrc)) { 3281cb0ef41Sopenharmony_ci throw new ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY({ 3291cb0ef41Sopenharmony_ci message: `cannot overwrite ${resolvedDest} with ${resolvedSrc}`, 3301cb0ef41Sopenharmony_ci path: dest, 3311cb0ef41Sopenharmony_ci syscall: 'cp', 3321cb0ef41Sopenharmony_ci errno: EINVAL, 3331cb0ef41Sopenharmony_ci code: 'EINVAL', 3341cb0ef41Sopenharmony_ci }); 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci return copyLink(resolvedSrc, dest); 3371cb0ef41Sopenharmony_ci} 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_cifunction copyLink(resolvedSrc, dest) { 3401cb0ef41Sopenharmony_ci unlinkSync(dest); 3411cb0ef41Sopenharmony_ci return symlinkSync(resolvedSrc, dest); 3421cb0ef41Sopenharmony_ci} 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_cimodule.exports = { cpSyncFn }; 345