MC logo

File Copier

  Some MPI Examples

clonefile.c
/*
 * Clone a file onto the various processors.
 *   mpiexec -hosts n ....clonefile file [todir]
 * Clones the file at its original abs path, unless todir is given, in which
 * case the file is placed there.
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <mpi.h>

#ifdef WIN32
#define SEPCHAR '\\'
#else
#define SEPCHAR '/'
#define MODES 1
#endif

#ifdef MODES
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif

char sepstr[2] = { SEPCHAR, '\0' };

#define BSIZE 1024

void die(char *m)
{
        perror(m);
        MPI_Finalize();
        exit(1);
}

main(int argc, char **argv)
{
        int nproc, myid;
        MPI_Init(&argc,&argv);
        MPI_Comm_size(MPI_COMM_WORLD,&nproc);
        MPI_Comm_rank(MPI_COMM_WORLD,&myid);

        if(argc < 2 || argc > 3) {
                fprintf(stderr, "Usage: %s file [ targetpath ]\n");
                MPI_Finalize();
                exit(3);
        }


        /* See if we need to munge the path on the output file. */
        char *fn = argv[1];
        if(myid != 0 && argc > 2) {
                char *fnpart = strrchr(fn, SEPCHAR);
                if(fnpart == NULL) fnpart = fn;
                else ++fnpart;
                char *newfn = malloc(strlen(fnpart) + strlen(argv[2]) + 2);
                if(!newfn) die("Malloc");
                strcat(strcat(strcpy(newfn, argv[2]), sepstr), fnpart);
                fn = newfn;
        }

        /* Open the file. */
        char *mode = "wb";
        if(myid == 0) mode = "rb";
        FILE *fd = fopen(fn, mode);
        if(!fd) die(fn);

        /* Transfer the file mode (which just sends a nice wasteful, 
           useless int on Windows or other machines which don't do 
           Unix modes). */
        unsigned int umode = 0644;
#ifdef MODES
        /* Get the Unix file modes. */
        struct stat status;
        if(stat(fn, &status) < 0) die("stat");
        umode = status.st_mode;
#endif
        MPI_Bcast(&umode, 1, MPI_INTEGER, 0, MPI_COMM_WORLD);
#ifdef MODES
        if(myid != 0) chmod(fn, umode);
#endif

        /* Copy the information. */
        char buf[BSIZE];
        while(1) {
                /* The root process reads a block from the file. */
                int nbyte;
                if(myid == 0) {
                        nbyte = fread(buf, 1, BSIZE, fd);
                        if(ferror(fd)) die(fn);
                }

                /* Send the file data around.  If the read return was 
                   zero (EOF), then everyone exits. */
                MPI_Bcast(&nbyte, 1, MPI_INTEGER, 0, MPI_COMM_WORLD);
                if(nbyte == 0) break;
                MPI_Bcast(buf, nbyte, MPI_CHAR, 0, MPI_COMM_WORLD);
                
                /* Non-roots write the block to disk. */
                if(myid != 0) {
                        int ret = fwrite(buf, 1, nbyte, fd);
                        if(ret < nbyte) die(fn);
                }
        }
        fclose(fd);

        MPI_Finalize();
        return 0;
}