1 // =================================
  2 // Copyright (c) 2022 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 using System.IO;
  9 using System.Os;
 10 using paths;
 11 
 12 bool TargetIsDirectory(const string& target)
 13 {
 14     byte[statBufSize] statBuf;
 15     int result = stat(target.Chars()&statBuf[0]statBufSize);
 16     if (result == -1)
 17     {
 18         return false;
 19     }
 20     FileStatus status;
 21     GetFileStatus(&statBuf[0]status);
 22     return status.fileType == FileType.directory;
 23 }
 24 
 25 void CopyFiles(const List<string>& filesconst string& targetconst List<FileType>& fileTypes
 26     bool targetDirExistsbool recursiveFileCopyOptions copyOptions)
 27 {
 28     long n = files.Count();
 29     for (long i = 0; i < n; ++i;)
 30     {
 31         const string& file = files[i];
 32         FileType fileType = fileTypes[i];
 33         if (fileType == FileType.directory)
 34         {
 35             DirectoryReader reader(file);
 36             DirectoryEntry dirEntry;
 37             List<string> sourceFilePaths;
 38             while (reader.Read(dirEntry))
 39             {
 40                 if (dirEntry.IsDot() || dirEntry.IsDotDot())
 41                 {
 42                     continue;
 43                 }
 44                 string sourceFilePath = Path.Combine(filedirEntry.name);
 45                 sourceFilePaths.Add(sourceFilePath);
 46             }
 47             string targetDir = target;
 48             if (targetDirExists)
 49             {
 50                 targetDir = Path.Combine(targetPath.GetFileName(file));
 51                 if (!Directory.Exists(targetDir))
 52                 {
 53                     MkDir(targetDir.Chars());
 54                 }
 55                 if ((copyOptions & FileCopyOptions.dontPreserveTimestamps) == FileCopyOptions.none)
 56                 {
 57                     DateTime accessTime;
 58                     DateTime modificationTime;
 59                     Directory.GetTimes(fileaccessTimemodificationTime);
 60                     Directory.SetTimes(targetDiraccessTimemodificationTime);
 61                 }
 62             }
 63             Copy(sourceFilePathstargetDirrecursivecopyOptions);
 64         }
 65         else if (fileType == FileType.regular)
 66         {
 67             string targetFilePath = Path.Combine(targetPath.GetFileName(file));
 68             File.Copy(filetargetFilePathcopyOptions);
 69         }
 70         else
 71         {
 72             throw Exception("'" + file + "' not regular or directory");
 73         }
 74     }
 75 }
 76 
 77 void Copy(const List<string>& filesconst string& targetbool recursiveFileCopyOptions copyOptions)
 78 {
 79     if (!TargetIsDirectory(target))
 80     {
 81         if (files.Count() == 1)
 82         {
 83             string file = files.Front();
 84             FileStatus status;
 85             Stat(file.Chars()status);
 86             if (status.fileType == FileType.directory)
 87             {
 88                 if (!recursive)
 89                 {
 90                     throw Exception("'" + file + "' is directory and not --recursive specified");
 91                 }
 92             }
 93             else if (status.fileType == FileType.regular)
 94             {
 95                 File.Copy(filetargetcopyOptions);
 96                 return;
 97             }
 98             else
 99             {
100                 throw Exception("'" + file + "' not regular or directory");
101             }
102         }
103         else if (files.Count() > 1)
104         {
105             throw Exception("'" + target + "' not directory");
106         }
107     }
108     List<FileType> fileTypes = GetFileTypes(filesrecursive);
109     bool targetDirExists = Directory.Exists(target);
110     if (!targetDirExists)
111     {
112         MkDir(target.Chars());
113     }
114     CopyFiles(filestargetfileTypestargetDirExistsrecursivecopyOptions);
115 }