/* * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab * Copyright (C) 2009 - DIGITEO - Allan CORNET * * This file must be used under the terms of the CeCILL. * This source file is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt * */ /*--------------------------------------------------------------------------*/ #ifndef _MSC_VER #include #include #include #include #include #include #include #include #include #include #include "copyfile.h" #include "BOOL.h" #include "charEncoding.h" #include "MALLOC.h" #include "isdir.h" #include "FileExist.h" #include "createdirectory.h" #include "PATH_MAX.h" #include "fullpath.h" /*--------------------------------------------------------------------------*/ static int CopyFileFunction_others(wchar_t *DestinationFilename, wchar_t *SourceFilename); static int CopyDirectoryFunction_others(wchar_t *DestinationDirectory, wchar_t *SourceDirectory); static int RecursiveCopyDirectory(char *DestinationDir, char *SourceDir); /*--------------------------------------------------------------------------*/ int CopyFileFunction(wchar_t *DestinationFilename, wchar_t *SourceFilename) { if (wcsicmp(DestinationFilename, SourceFilename) == 0) { return EPERM; } return CopyFileFunction_others(DestinationFilename, SourceFilename); } /*--------------------------------------------------------------------------*/ int CopyDirectoryFunction(wchar_t *DestinationDirectory, wchar_t *SourceDirectory) { /* remove last file separator if it does not exists */ if ( (SourceDirectory[wcslen(SourceDirectory) - 1] == L'\\') || (SourceDirectory[wcslen(SourceDirectory) - 1] == L'/') ) { SourceDirectory[wcslen(SourceDirectory) - 1] = L'\0'; } /* remove last file separator if it does not exists */ if ( (DestinationDirectory[wcslen(DestinationDirectory) - 1] == L'\\') || (DestinationDirectory[wcslen(DestinationDirectory) - 1] == L'/') ) { DestinationDirectory[wcslen(DestinationDirectory) - 1] = L'\0'; } return CopyDirectoryFunction_others(DestinationDirectory, SourceDirectory); } /*--------------------------------------------------------------------------*/ /* Copy file with all attributes */ static int CopyFileFunction_others(wchar_t *DestinationFilename, wchar_t *SourceFilename) { char *pStrDest = wide_string_to_UTF8(DestinationFilename); char *pStrSrc = wide_string_to_UTF8(SourceFilename); char strDestFullPath[PATH_MAX * 2 + 1]; char strSrcFullPath[PATH_MAX * 2 + 1]; int sfd = -1; int dfd = -1; struct stat st; char buf[1024 * 32]; char *ptr = NULL; int nread = 0, nwritten = 0; int status = 0; get_full_path(strDestFullPath, pStrDest, PATH_MAX * 2); get_full_path(strSrcFullPath, pStrSrc, PATH_MAX * 2); if (strcmp(strDestFullPath, strSrcFullPath) == 0) { status = EPERM; goto err; } if ((sfd = open (pStrSrc, O_RDONLY, 0)) < 0) { status = errno; goto err; } if (fstat (sfd, &st) < 0) { status = errno; goto err; } if ((dfd = open (pStrDest, O_WRONLY | O_CREAT | O_TRUNC, st.st_mode & 0777)) < 0) { status = errno; goto err; } while ((nread = read (sfd, buf, sizeof (buf))) > 0) { ptr = buf; while (nread > 0) { nwritten = write (dfd, ptr, nread); if (nwritten <= 0) { status = errno; goto err; } nread -= nwritten; ptr += nwritten; } } if (nread < 0) { status = errno; goto err; } if (close (dfd) < 0) { status = errno; goto err; } fchmod (dfd, st.st_mode & 0777); close (sfd); if (pStrDest) { FREE(pStrDest); pStrDest = NULL; } if (pStrSrc) { FREE(pStrSrc); pStrSrc = NULL; } return 0; err: if (sfd >= 0) { close (sfd); } if (dfd >= 0) { close (dfd); unlink (pStrDest); } if (pStrDest) { FREE(pStrDest); pStrDest = NULL; } if (pStrSrc) { FREE(pStrSrc); pStrSrc = NULL; } return status; } /*--------------------------------------------------------------------------*/ static int CopyDirectoryFunction_others(wchar_t *DestinationDirectory, wchar_t *SourceDirectory) { char *pStrDest = wide_string_to_UTF8(DestinationDirectory); char *pStrSrc = wide_string_to_UTF8(SourceDirectory); int ierr = 0; /* we check directory source exists */ if (!isdir(pStrSrc)) { if (pStrDest) { FREE(pStrDest); pStrDest = NULL; } FREE(pStrSrc); return ENOTDIR; } /* we check destination directory exists */ if (!isdir(pStrDest)) { if (FileExistW(DestinationDirectory)) { FREE(pStrDest); FREE(pStrSrc); return ENOTDIR; } else { if (!createdirectoryW(DestinationDirectory)) { FREE(pStrDest); FREE(pStrSrc); return ENOTDIR; } } } ierr = RecursiveCopyDirectory(pStrDest, pStrSrc); FREE(pStrDest); FREE(pStrSrc); if (ierr) { return errno; } return 0; } /*--------------------------------------------------------------------------*/ static int RecursiveCopyDirectory(char *DestinationDir, char *SourceDir) { DIR *dir; struct dirent *ent; dir = opendir(SourceDir) ; if (dir == NULL) { return errno; } while ((ent = readdir(dir)) != NULL) { char *filenameSRC = NULL; char *filenameDST = NULL; if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { continue ; } filenameSRC = (char*)MALLOC(sizeof(char) * (strlen(SourceDir) + 1 + strlen(ent->d_name) + 1 + 1)) ; filenameDST = (char*)MALLOC(sizeof(char) * (strlen(DestinationDir) + 1 + strlen(ent->d_name) + 1 + 1)) ; sprintf(filenameSRC, "%s/%s", SourceDir, ent->d_name); if (DestinationDir[strlen(DestinationDir) - 1] == '/') { sprintf(filenameDST, "%s%s", DestinationDir, ent->d_name); } else { sprintf(filenameDST, "%s/%s", DestinationDir, ent->d_name); } if (isdir(filenameSRC)) { int ierr = 0; BOOL bOK = createdirectory(filenameDST); if (!bOK) { FREE(filenameDST); FREE(filenameSRC); closedir(dir); return EACCES; } ierr = RecursiveCopyDirectory(filenameDST, filenameSRC); if (ierr) { FREE(filenameDST); FREE(filenameSRC); closedir(dir); return ierr; } } else { wchar_t* wcfileDest = to_wide_string(filenameDST); wchar_t* wcfileSrc = to_wide_string(filenameSRC); int ierr = CopyFileFunction_others(wcfileDest, wcfileSrc); FREE(wcfileDest); FREE(wcfileSrc); if (ierr) { FREE(filenameDST); FREE(filenameSRC); closedir(dir); return ierr; } } FREE(filenameDST); FREE(filenameSRC); } closedir(dir); return 0; } /*--------------------------------------------------------------------------*/ #endif /* #ifndef _MSC_VER */ /*--------------------------------------------------------------------------*/