3

I am looking for a simple example on how to copy a file from one directory to another in C. The program should only use cross platform functions that are native to C.

mshamma
  • 326
  • 3
  • 13
user63898
  • 29,839
  • 85
  • 272
  • 514
  • 6
    "Native" functions are roughly the opposite of "cross-platform" functions. Native functions are those that are "native" to an OS, and therefore specific to it. "Cross-platform" functions are available everywhere, by virtue of being built on top of those native functions. – MSalters Sep 01 '11 at 07:49
  • You can use `#ifdef` `#else` and `#endif` those pre-processing blocks to call platform-related functions and let compiler decide which one to call. – Stan Sep 01 '11 at 08:20
  • @MSalters: Well put, but I think starting a question with "I looking" indicates a non-*native* english speaker. :-/ I myself interpret the OP's meaning was that he/she wanted to use a library that under the hood calls "copy file" natives. It would thusly exclude the (unfortunately) upvoted answers here about rolling one's own copy based on merely reading a file and writing to another... – HostileFork says dont trust SE Sep 01 '11 at 19:12

7 Answers7

9

Here is a simple untested C program that does what you need:

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argn, char * argv[]) {

    int src_fd, dst_fd, n, err;
    unsigned char buffer[4096];
    char * src_path, dst_path;

    // Assume that the program takes two arguments the source path followed
    // by the destination path.

    if (argn != 3) {
        printf("Wrong argument count.\n");
        exit(1);
    }

    src_path = argv[1];
    dst_path = argv[2];

    src_fd = open(src_path, O_RDONLY);
    dst_fd = open(dst_path, O_CREAT | O_WRONLY);

    while (1) {
        err = read(src_fd, buffer, 4096);
        if (err == -1) {
            printf("Error reading file.\n");
            exit(1);
        }
        n = err;

        if (n == 0) break;

        err = write(dst_fd, buffer, n);
        if (err == -1) {
            printf("Error writing to file.\n");
            exit(1);
        }
    }

    close(src_fd);
    close(dst_fd);
}
therealak12
  • 1,178
  • 2
  • 12
  • 26
mshamma
  • 326
  • 3
  • 13
  • In some UNIX systems you need to these includes too: #include #include – therealak12 Apr 26 '20 at 19:11
  • This program works well, except the created file doesn't have any permissions (I tested in Ubuntu). In order to give required permissions to the copied file change the dst_fd = ... line to dst_fd = open(dst_path, O_WRONLY | O_CREAT | O_EXCL, 0666); – therealak12 Apr 26 '20 at 19:30
6
open source file read-only
create destination file for write
while there's still data in source file
    read data from source file
    write it to destination file
close both files

I'm sure you can do it!

Didier Trosset
  • 36,376
  • 13
  • 83
  • 122
2

The correct way to copy files in C++ using dirent.h is below. Note that dirent.h is part of Linux but not included in Windows. For Windows look here.

For Windows Visual C++:

 // CopyAll_Windows.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<stdio.h>
#include"dirent.h"   //Copy dirent.h to folder where stdafx.h is and add to project
#include<errno.h>
#include<sys/stat.h>
#include <iostream>

#define MAX 1024
#define MAX_FILE_NAME_LEN 256

using namespace std;

int main()
{
    string homedir = "C:\\Users\\Tom\\Documents";
    cerr << endl << "Home =  " << homedir.c_str() << endl;
    string SrcPath = homedir + "\\Source 1";
    string DestPath = homedir + "\\Dest 1\\Dest 1";
    string DestPath_mkdir = "\"" + DestPath + "\"";
    string command = "mkdir " + DestPath_mkdir;
    cerr << endl << "Command = " << command.c_str() << endl << endl;
    system(command.c_str());
    const char *arSrcPath = SrcPath.c_str();
    const char *arDestPath = DestPath.c_str();

    struct dirent* spnDirPtr;    /* struct dirent to store all files*/
    DIR* pnWriteDir = NULL;    /*DIR Pointer to open Dir*/
    pnWriteDir = opendir(arDestPath);

    if (!pnWriteDir)
        cerr << endl << "ERROR! Write Directory can not be open" << endl;

    DIR* pnReadDir = NULL;    /*DIR Pointer to open Dir*/
    pnReadDir = opendir(arSrcPath);

    if (!pnReadDir || !pnWriteDir)
        cerr << endl << "ERROR! Read or Write Directory can not be open" << endl << endl;

    else
    {
        int nErrNo = 0;

        while ((spnDirPtr = readdir(pnReadDir)) != NULL)
        {
            char readPath[MAX_FILE_NAME_LEN] = { 0 };
            memset(readPath, 0, MAX_FILE_NAME_LEN);

            // Following line needed to get real path for "stat" call
            _snprintf_s(readPath, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arSrcPath, spnDirPtr->d_name);
            struct stat st_buf;
            stat(readPath, &st_buf);

            if (S_ISDIR(st_buf.st_mode))
            {
                cerr << endl << "Reading directory here..." << endl;
                continue;
            }
            else if (S_ISREG(st_buf.st_mode))
            {
                if (nErrNo == 0)
                    nErrNo = errno;

                cerr << endl << "Now reading and writing file " << spnDirPtr->d_name << endl;
                char strSrcFileName[MAX_FILE_NAME_LEN] = { 0 };
                memset(strSrcFileName, 0, MAX_FILE_NAME_LEN);

                // Following line needed to get real path for "pnReadFile"
                _snprintf_s(strSrcFileName, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arSrcPath, spnDirPtr->d_name);

                FILE* pnReadFile;
                errno_t err_read;

                if ((err_read = fopen_s(&pnReadFile, strSrcFileName, "r")) == 0)
                {
                    cerr << endl << "Now reading file " << strSrcFileName << endl;
                    char strDestFileName[MAX_FILE_NAME_LEN] = { 0 };
                    memset(strDestFileName, 0, MAX_FILE_NAME_LEN);

                    // Following line needed to get real path for "pnWriteFile"
                    _snprintf_s(strDestFileName, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arDestPath, spnDirPtr->d_name);

                    FILE* pnWriteFile;  /*File Pointer to write in file*/
                    errno_t err_write;

                    if ((err_write = fopen_s(&pnWriteFile, strDestFileName, "w")) == 0)
                    {
                        cerr << endl << "Now writing file " << strDestFileName << endl;
                        char buffer[MAX] = { 0 };    /*Buffer to store files content*/

                        while (fgets(buffer, MAX, pnReadFile))
                        {
                            fputs(buffer, pnWriteFile);
                        }
                        fclose(pnWriteFile);
                    }
                    else
                    {
                        cerr << endl << "Error! Unable to open file for writing " << strDestFileName << endl;
                    }
                    fclose(pnReadFile);
                }
                else
                {
                    cerr << endl << "ERROR! File Could not be open for reading" << endl;
                }
            }
        }
        if (nErrNo != errno)
            cerr << endl << "ERROR Occurred!" << endl;
        else
            cerr << endl << "Process Completed" << endl << endl;
    }
    closedir(pnReadDir);
    closedir(pnWriteDir);

    return 0;
}

For Linux Eclipse C++:

// CopyAll_linux.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"
#include<stdio.h>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<dirent.h>
#include<errno.h>
#include<sys/stat.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

#define MAX 1024
#define MAX_FILE_NAME_LEN 256

using namespace std;

int main()
{
    const char *homedir;
    if ((homedir = getenv("HOME")) == NULL) {
        homedir = getpwuid(getuid())->pw_dir;
    }
    cerr << endl << "Home =  " <<  homedir << endl;
    string hd(homedir);
    string SrcPath = hd + "/Source 1";
    string DestPath = hd + "/Dest 1/Dest 1";
    string DestPath_mkdir = "\"" + DestPath + "\"";
    string command = "mkdir -p " + DestPath_mkdir;
    cerr << endl << "Command = " <<  command.c_str() << endl << endl;
    system(command.c_str());
    const char *arSrcPath = SrcPath.c_str();
    const char *arDestPath = DestPath.c_str();

    struct dirent* spnDirPtr;    /* struct dirent to store all files*/
    DIR* pnWriteDir = NULL;    /*DIR Pointer to open Dir*/
    pnWriteDir = opendir(arDestPath);

    if (!pnWriteDir)
        cerr << endl << "ERROR! Write Directory can not be open" << endl;

    DIR* pnReadDir = NULL;    /*DIR Pointer to open Dir*/
    pnReadDir = opendir(arSrcPath);

    if (!pnReadDir || !pnWriteDir)
        cerr << endl <<"ERROR! Read or Write Directory can not be open" << endl << endl;

    else
    {
        int nErrNo = 0;

        while ((spnDirPtr = readdir(pnReadDir)) != NULL)
        {
            char readPath[MAX_FILE_NAME_LEN] = { 0 };
            memset(readPath, 0, MAX_FILE_NAME_LEN);
            // Following line needed to get real path for "stat" call
            snprintf(readPath, MAX_FILE_NAME_LEN, "%s/%s", arSrcPath, spnDirPtr->d_name);
            struct stat st_buf;
            stat(readPath, &st_buf);

            if (S_ISDIR(st_buf.st_mode))
            {
                cerr << endl << "Reading directory here..." << endl;
                continue;
            }
            else if (S_ISREG(st_buf.st_mode))
            {
                if (nErrNo == 0)
                    nErrNo = errno;

                cerr << endl << "Now reading and writing file "<< spnDirPtr->d_name << endl;
                char strSrcFileName[MAX_FILE_NAME_LEN] = { 0 };
                memset(strSrcFileName, 0, MAX_FILE_NAME_LEN);
                // Following line needed to get real path for "pnReadFile"
                snprintf(strSrcFileName, MAX_FILE_NAME_LEN, "%s/%s", arSrcPath, spnDirPtr->d_name);
                FILE* pnReadFile;
                pnReadFile = fopen(strSrcFileName, "r");

                if (pnReadFile == NULL)
                    cerr << endl << "Null pointer on read file ..." << endl;

                if (pnReadFile)
                {
                    cerr << endl << "Now reading file " << strSrcFileName << endl;
                    char strDestFileName[MAX_FILE_NAME_LEN] = { 0 };
                    memset(strDestFileName, 0, MAX_FILE_NAME_LEN);
                    // Following line needed to get real path for "pnWriteFile"
                    snprintf(strDestFileName, MAX_FILE_NAME_LEN, "%s/%s", arDestPath, spnDirPtr->d_name);
                    FILE* pnWriteFile = fopen(strDestFileName, "w");    /*File Pointer to write in file*/

                    if (pnWriteFile)
                    {
                        cerr << endl << "Now writing file " << strDestFileName << endl;
                        char buffer[MAX] = { 0 };    /*Buffer to store files content*/

                        while (fgets(buffer, MAX, pnReadFile))
                        {
                            fputs(buffer, pnWriteFile);
                        }
                        fclose(pnWriteFile);
                    }
                    else
                    {
                        cerr << endl << "Error! Unable to open file for writing " << strDestFileName << endl;
                    }
                    fclose(pnReadFile);
                }
                else
                {
                    cerr << endl << "ERROR! File Could not be open for reading" << endl;
                }
            }
        }
        if (nErrNo != errno)
            cerr << endl << "ERROR Occurred!" << endl;
        else
            cerr << endl << "Process Completed" << endl << endl;
    }
    closedir(pnReadDir);
    closedir(pnWriteDir);

    return 0;
}

Visual Studio C++ dll:

 // copy_all_dll.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include<stdio.h>
#include"dirent.h"   //Copy dirent.h to folder where stdafx.h is and add to project
#include<errno.h>
#include<sys/stat.h>
#include <iostream>

#define MAX 1024
#define MAX_FILE_NAME_LEN 256

using namespace std;

BOOL DirectoryExists(const char* dirName);

extern "C"  __declspec(dllexport) char*  copy_combos_all(char *source, char *dest)

{
    char *pnError = "";

    BOOL dest_exists = DirectoryExists(dest);

    if (!dest_exists)
    {
        string DestPath(dest);
        DestPath = "\"" + DestPath + "\"";
        string command = "mkdir " + DestPath;
        system(command.c_str());
    }

    const char *arSrcPath = source;
    const char *arDestPath = dest;

    struct dirent* spnDirPtr;    /* struct dirent to store all files*/
    DIR* pnWriteDir = NULL;    /*DIR Pointer to open Dir*/
    pnWriteDir = opendir(arDestPath);
    if (!pnWriteDir)
    {
        pnError =  "ERROR! Write Directory can not be open";
        return pnError;
    }
    DIR* pnReadDir = NULL;    /*DIR Pointer to open Dir*/
    pnReadDir = opendir(arSrcPath);

    if (!pnReadDir) 
    {
        pnError = "ERROR! Read Directory can not be open";
        if (pnWriteDir)
        {
            closedir(pnWriteDir);
        }
        return pnError;
    }
    else
    {
        int nErrNo = 0;

        while ((spnDirPtr = readdir(pnReadDir)) != NULL)
        {
            char readPath[MAX_FILE_NAME_LEN] = { 0 };
            memset(readPath, 0, MAX_FILE_NAME_LEN);

            // Following line needed to get real path for "stat" call
            _snprintf_s(readPath, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arSrcPath, spnDirPtr->d_name);
            struct stat st_buf;
            stat(readPath, &st_buf);

            if (S_ISDIR(st_buf.st_mode))
            {
                continue;
            }
            else if (S_ISREG(st_buf.st_mode))
            {
                if (nErrNo == 0)
                    nErrNo = errno;

                char strSrcFileName[MAX_FILE_NAME_LEN] = { 0 };
                memset(strSrcFileName, 0, MAX_FILE_NAME_LEN);

                // Following line needed to get real path for "pnReadFile"
                _snprintf_s(strSrcFileName, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arSrcPath, spnDirPtr->d_name);

                FILE* pnReadFile;
                errno_t err_read;

                if ((err_read = fopen_s(&pnReadFile, strSrcFileName, "r")) == 0)
                {
                    char strDestFileName[MAX_FILE_NAME_LEN] = { 0 };
                    memset(strDestFileName, 0, MAX_FILE_NAME_LEN);

                    // Following line needed to get real path for "pnWriteFile"
                    _snprintf_s(strDestFileName, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arDestPath, spnDirPtr->d_name);

                    FILE* pnWriteFile;
                    errno_t err_write;

                    if ((err_write = fopen_s(&pnWriteFile, strDestFileName, "w")) == 0)    /*File Pointer to write in file*/
                    {
                        char buffer[MAX] = { 0 };    /*Buffer to store files content*/

                        while (fgets(buffer, MAX, pnReadFile))
                        {
                            fputs(buffer, pnWriteFile);
                        }
                        fclose(pnWriteFile);
                    }
                    else
                    {
                        pnError = "Error! Unable to open file for writing ";
                        return pnError;
                    }
                    fclose(pnReadFile);
                }
                else
                {
                    pnError = "ERROR! File Could not be open for reading";
                    return pnError;
                }
            }
        }
        if (nErrNo != errno)
        {
            pnError = "ERROR Occurred!";
        }
        else
        {
            pnError = "Process Completed";
        }
    }
    if (pnReadDir)
    {
        closedir(pnReadDir);
    }
    if (pnWriteDir)
    {
        closedir(pnWriteDir);
    }

    return pnError;
}

BOOL DirectoryExists(const char* dirName) {
    DWORD attribs = ::GetFileAttributesA(dirName);
    if (attribs == INVALID_FILE_ATTRIBUTES) {
        return false;
    }
    return (attribs & FILE_ATTRIBUTE_DIRECTORY);
}

For the dll, you call call it as following:

VB.Net:

<DllImport("copy_all.dll", CallingConvention:=CallingConvention.Cdecl)>
Public Shared Function copy_all(source As String, dest As String) As StringBuilder
End Function

Sub copyAll()

    Dim source, dest, homedir As String
    homedir = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
    source = homedir & "\Source"
    dest = homedir & "\Dest"

    If Not My.Computer.FileSystem.DirectoryExists(dest) Then
        My.Computer.FileSystem.CreateDirectory(dest)
    End If

    Dim errorMessage As String
    errorMessage = ""
    Dim sb As New StringBuilder()
    sb = copy_all(source, dest)
    errorMessage = sb.ToString

    If (errorMessage <> "") Then
        MessageBox.Show(errorMessage)
    End If


End Sub

Visual C#:

[DllImport("copy_all.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr copy_all(string source, string dest);

public void copyAll()
{

    string homedir = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    string source = homedir + "\\Source";
    string dest = homedir + "\\Dest";
    string error = "";

    if (!Directory.Exists(dest))
        Directory.CreateDirectory(dest);

    IntPtr ptr = copy_all(source, dest);

    error = Marshal.PtrToStringAnsi(ptr);

    if (error != "")

        MessageBox.Show(error);

}
te7
  • 601
  • 1
  • 6
  • 23
1

@Mu Qiao mentioned boost::filesystem. Specifically you'd want to look for examples of copy_file, though you can copy directories too.

If you're interested in getting fancy with asynchronous I/O, my impression is that boost::asio has interesting implementations that take advantage of platform abilities to let you use the CPU while waiting for the disk, just as it does for the network:

How to perform Cross-Platform Asynchronous File I/O in C++

(Note: Lately the asio library has been coming to mind lately a lot, but I always have to offer the disclaimer that I haven't used it in a project and kind of have no idea what its limitations are. So take my mention of it with a grain of salt.)

There are other cross-platform libraries offering this kind of functionality, if you're willing to do the buy-in, always a matter of taste and needs. I myself like Qt for a lot of reasons, and it does happen to offer a QFile::copy method:

http://doc.qt.nokia.com/latest/qfile.html#copy

Community
  • 1
  • 1
0
/*
 *
 * Module    : Copy Multiple from Src dir to Dest dir
 * Author    : Mohd Asif
 * Date     : 12-March-2013
 * Description    : This code will copy all the files from Src dir to Dest Dir 
 *    instead of onother directory inside src dir
 * */

#include<stdio.h>
#include<stdio.h>
#include<dirent.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/stat.h>
#define MAX 1024

int main()
{
    char    arSrcPath[]    = "/home/mpe4/Src";    /*Source directory path*/
    char    arDestPath[]    = "/home/mpe4/Dest";    /*dest directory path*/
    struct    dirent* spnDirPtr;    /* struct dirent to store all files*/

    DIR* pnOpenDir = NULL;    /*DIR Pointer to open Dir*/
    DIR* pnReadDir = NULL;    /*DIR POinter to read directory*/

    pnOpenDir = opendir(arSrcPath); 

    if(!pnOpenDir)
    printf("\n ERROR! Directory can not be open");

    else
    {    
    int nErrNo = 0;
    while(spnDirPtr = readdir(pnOpenDir))
    {
        if(nErrNo == 0)
        nErrNo = errno;
        printf("\n Now writing %s file...",spnDirPtr->d_name);

        printf("\n dest file name = %s/%s\n", arDestPath, spnDirPtr->d_name);

        struct stat st_buf;
        stat(spnDirPtr->d_name, &st_buf);
        if (S_ISDIR (st_buf.st_mode))
        {
            continue;
        }
        else if (S_ISREG (st_buf.st_mode))
        {
            FILE* pnReadFile = fopen(spnDirPtr->d_name,"r");

            if(pnReadFile)
            {
                printf("\n Now reading %s file...",spnDirPtr->d_name);

                char strDestFileName[MAX] = {0};
                sprintf(strDestFileName, "%s/%s", arDestPath, spnDirPtr->d_name);
                printf("\n dest file name = %s\n", strDestFileName);

                FILE* pnWriteFile  = fopen(strDestFileName, "w");    /*File Pointer to write in file*/
                if(pnWriteFile)
                {
                    char buffer[MAX] = {0};    /*Buffer to store files content*/

                        while(fgets(buffer, MAX, pnReadFile))
                        {
                            fputs(buffer, pnWriteFile);
                        }
                    fclose(pnWriteFile);
                }
            else
            {
                printf("\n Unable to open file %s", strDestFileName);
            }
            fclose(pnReadFile);
    }
    else
    {
        printf ("\nERROR! File Could not be open for reading");
    }
    }
    }
    if(nErrNo != errno)
        printf ("\nERROR Occurred!\n");
    else
        printf ("\nProcess Completed\n");

    }
    closedir(pnOpenDir);
    return 0;
}    
M Asif
  • 9
  • 2
0

I made some changes to @te7 answer to copy just one file from one folder to another on MAC. I tried to modify his code to just copy one file but it was partially writing file to destination. So I use different code for file read/write

void copyFile(string srcDirPath, string destDirPath, string fileName)
{


string command = "mkdir -p " + destDirPath;
cerr << endl << "Command = " <<  command.c_str() << endl << endl;
system(command.c_str());


DIR* pnWriteDir = NULL;    /*DIR Pointer to open Dir*/
pnWriteDir = opendir(destDirPath.c_str());

if (!pnWriteDir)
    cerr << endl << "ERROR! Write Directory can not be open" << endl;

DIR* pnReadDir = NULL;    /*DIR Pointer to open Dir*/
pnReadDir = opendir(srcDirPath.c_str());

if (!pnReadDir || !pnWriteDir)
    cerr << endl <<"ERROR! Read or Write Directory can not be open" << endl << endl;

else
{
    string srcFilePath = srcDirPath + fileName;
    const char * strSrcFileName = srcFilePath.c_str();
    fstream in, out;
    in.open(strSrcFileName, fstream::in|fstream::binary);

    if (in.is_open()) {
        cerr << endl << "Now reading file " << strSrcFileName << endl;

        string destFilePath = destDirPath + fileName;
        const char * strDestFileName = destFilePath.c_str();
        out.open(strDestFileName, fstream::out);

        char tmp;
        while(in.read(&tmp, 1))
        {
            out.write(&tmp, 1);
        }
        out.close();
        in.close();
    }
    else
        cerr << endl << "ERROR! File Could not be open for reading" << endl;
}
closedir(pnReadDir);
closedir(pnWriteDir);
}
0

Another alternative is something like this:

#ifdef SOME_OS
  #define COPY_STR "copy %s %s"  // some sort of OS-specific syntax

#elif defined SOME_OTHER_OS
  #define COPY_STR "%s cpy %s"   // some sort of OS-specific syntax

#else
  #error "error text"
#endif

...

#include <stdio.h>   //sprintf()
#include <stdlib.h>  //system()

char copy_str[LARGE_ENOUGH];
char* source;
char* dest;
...

sprintf (copy_str, COPY_STR, source, dest);
system (copy_str);
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    A note on using approaches like this: breaking into a swiss army knife shell for such a task creates risks...either accidental mistakes or vulnerability to hackers. On Windows, for instance, someone could provide a `source` of `"foo.txt bar.txt"` and a `dest` of `"& del *.*"`...the ampersand making it chain the commands together as `"copy foo.txt bar.txt & del *.*"`. Always remember Bobby Tables!!! http://xkcd.com/327/ – HostileFork says dont trust SE Sep 01 '11 at 10:15
  • If you want to make it hacker proof, you would have to encrypt all string literals etc too. Anyway, nothing in the OPs post indicates that this is a concern of theirs, nor that they are even using Windows. – Lundin Sep 01 '11 at 11:00
  • 1
    You *absolutely do not* need to encrypt string literals to ensure that a line of code can only copy files and not delete them. A function like `boost::filesystem::copy_file` isn't subject such concerns. And I only mentioned Windows because your first string example was `COPY_STR "copy %s %s"` (instead of, say `COPY_STR "cp %s %s"`). The same kind of mischief is possible when you use this class of technique in any OS, if ever you pass a string that comes from a source besides a hardcoded value in your program. Sanitization becomes an issue, and often a very serious one. – HostileFork says dont trust SE Sep 01 '11 at 15:13
  • Notice also I didn't say the technique isn't worth demonstrating in this thread. But the potential problems need to be mentioned...and that it's really only something to use in situations where you want expedience in throwaway code. Plus I didn't even bother pointing out that you're invoking an entire command interpreter and environment instead of using something that translates down into specific native filesystem calls. (Which is another reason not to do it this way, though in my mind the one of less overall concern as that's just performance vs a potentially disastrous correctness issue.) – HostileFork says dont trust SE Sep 01 '11 at 15:19
  • First, boost is probably not portable, as it isn't standard C++. The OP asked for cross-platform, without mentioning any specifics. Anyway, this is obviously a C answer. Indeed system() comes with additional overhead, but since file copying is very slow by itself, it may or may not be an issue. If you are up for a whole lotta file copying as fast as possible, you are naturally better off by calling the OS API straight away (since fprintf etc comes with an interpreter too) and put the OS-specific compiler switches around the file I/O code. – Lundin Sep 02 '11 at 06:35
  • [1] If you have doubts about boost's validity, I suggest you either invest some time reading the threads in the boost review process or ask your own question a la: http://stackoverflow.com/questions/2342037/to-which-extent-is-boost-does-it-equivalent-to-very-portable-use-it – HostileFork says dont trust SE Sep 02 '11 at 07:13
  • [2] I will (er...gently?) reiterate that the subject of input validation and sanitization is a topic you really should commit some time to studying if you are going to actually advocate this kind of approach over something more constrained. Especially to *keep arguing* when confronted with the facts of the matter. C'mon, srsly? – HostileFork says dont trust SE Sep 02 '11 at 07:17
  • 1) In embedded systems for example, you'll be happy if you just find a compiler following the C++ standard. Support for non-standard 3rd party libraries will be very rare. Also, it is pointless to ask desktop people about how portable boost is, because they don't think anything in the world exists beyond PC and Linux. 2) I never argued against what you said, it is indeed a security concern. But so is hard-coded string literals in the binary, a hacker could alter those as well as they could alter program input/output. Either you make the program secure all the way or security won't be relevant. – Lundin Sep 02 '11 at 07:56
  • We're at the point where StackOverflow is now warning me that the discussion is too long. It actually seems that when all is said and done we don't fundamentally disagree on anything (other than the portability of boost, which I suggest you argue elsewhere). So I'll just ask you to move the caveats we've discussed from this thread into your answer, and we leave it at that!! These days I'm pretty sure that we're the only two people reading this anyway. :-P – HostileFork says dont trust SE Sep 02 '11 at 08:56