/*
* 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;
}