17d0a6c19SBarry Smith 2e5c89e4eSSatish Balay /* 3e5c89e4eSSatish Balay Code for opening and closing files. 4e5c89e4eSSatish Balay */ 5c6db04a5SJed Brown #include <petscsys.h> 6e5c89e4eSSatish Balay #if defined(PETSC_HAVE_PWD_H) 7e5c89e4eSSatish Balay #include <pwd.h> 8e5c89e4eSSatish Balay #endif 9e5c89e4eSSatish Balay #include <ctype.h> 10e5c89e4eSSatish Balay #include <sys/stat.h> 11e5c89e4eSSatish Balay #if defined(PETSC_HAVE_UNISTD_H) 12e5c89e4eSSatish Balay #include <unistd.h> 13e5c89e4eSSatish Balay #endif 14e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SYS_UTSNAME_H) 15e5c89e4eSSatish Balay #include <sys/utsname.h> 16e5c89e4eSSatish Balay #endif 17e5c89e4eSSatish Balay #include <fcntl.h> 18e5c89e4eSSatish Balay #include <time.h> 19e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H) 20e5c89e4eSSatish Balay #include <sys/systeminfo.h> 21e5c89e4eSSatish Balay #endif 225ea2b939SDuncan Campbell #include <petsc/private/petscimpl.h> 23e5c89e4eSSatish Balay 24480cf27aSJed Brown /* 25480cf27aSJed Brown Private routine to delete tmp/shared storage 26480cf27aSJed Brown 27480cf27aSJed Brown This is called by MPI, not by users. 28480cf27aSJed Brown 2912801b39SBarry Smith Note: this is declared extern "C" because it is passed to MPI_Comm_create_keyval() 30480cf27aSJed Brown 31480cf27aSJed Brown */ 32d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelTmpShared(MPI_Comm comm, PetscMPIInt keyval, void *count_val, void *extra_state) 33d71ae5a4SJacob Faibussowitsch { 34480cf27aSJed Brown PetscFunctionBegin; 359566063dSJacob Faibussowitsch PetscCallMPI(PetscInfo(NULL, "Deleting tmp/shared data in an MPI_Comm %ld\n", (long)comm)); 369566063dSJacob Faibussowitsch PetscCallMPI(PetscFree(count_val)); 37480cf27aSJed Brown PetscFunctionReturn(MPI_SUCCESS); 38480cf27aSJed Brown } 39e5c89e4eSSatish Balay 40e5c89e4eSSatish Balay /*@C 41e5c89e4eSSatish Balay PetscGetTmp - Gets the name of the tmp directory 42e5c89e4eSSatish Balay 43d083f849SBarry Smith Collective 44e5c89e4eSSatish Balay 45e5c89e4eSSatish Balay Input Parameters: 46e5c89e4eSSatish Balay + comm - MPI_Communicator that may share /tmp 47e5c89e4eSSatish Balay - len - length of string to hold name 48e5c89e4eSSatish Balay 49f899ff85SJose E. Roman Output Parameter: 50e5c89e4eSSatish Balay . dir - directory name 51e5c89e4eSSatish Balay 52e5c89e4eSSatish Balay Options Database Keys: 5310699b91SBarry Smith + -shared_tmp - indicates the directory is shared among the MPI ranks 5410699b91SBarry Smith . -not_shared_tmp - indicates the directory is not shared among the MPI ranks 5510699b91SBarry Smith - -tmp tmpdir - name of the directory you wish to use as /tmp 56e5c89e4eSSatish Balay 57e5c89e4eSSatish Balay Environmental Variables: 58811af0c4SBarry Smith + `PETSC_SHARED_TMP` - indicates the directory is shared among the MPI ranks 59811af0c4SBarry Smith . `PETSC_NOT_SHARED_TMP` - indicates the directory is not shared among the MPI ranks 60811af0c4SBarry Smith - `PETSC_TMP` - name of the directory you wish to use as /tmp 61e5c89e4eSSatish Balay 62e5c89e4eSSatish Balay Level: developer 63e5c89e4eSSatish Balay 64811af0c4SBarry Smith .seealso: `PetscSharedTmp()`, `PetscSharedWorkingDirectory()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 65e5c89e4eSSatish Balay @*/ 66d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGetTmp(MPI_Comm comm, char dir[], size_t len) 67d71ae5a4SJacob Faibussowitsch { 68ace3abfcSBarry Smith PetscBool flg; 69e5c89e4eSSatish Balay 70e5c89e4eSSatish Balay PetscFunctionBegin; 719566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_TMP", dir, len, &flg)); 7248a46eb9SPierre Jolivet if (!flg) PetscCall(PetscStrncpy(dir, "/tmp", len)); 733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74e5c89e4eSSatish Balay } 75e5c89e4eSSatish Balay 76e5c89e4eSSatish Balay /*@C 77e5c89e4eSSatish Balay PetscSharedTmp - Determines if all processors in a communicator share a 78e5c89e4eSSatish Balay /tmp or have different ones. 79e5c89e4eSSatish Balay 80d083f849SBarry Smith Collective 81e5c89e4eSSatish Balay 82811af0c4SBarry Smith Input Parameter: 83e5c89e4eSSatish Balay . comm - MPI_Communicator that may share /tmp 84e5c89e4eSSatish Balay 85811af0c4SBarry Smith Output Parameter: 86811af0c4SBarry Smith . shared - `PETSC_TRUE` or `PETSC_FALSE` 87e5c89e4eSSatish Balay 88e5c89e4eSSatish Balay Options Database Keys: 8910699b91SBarry Smith + -shared_tmp - indicates the directory is shared among the MPI ranks 9010699b91SBarry Smith . -not_shared_tmp - indicates the directory is not shared among the MPI ranks 9110699b91SBarry Smith - -tmp tmpdir - name of the directory you wish to use as /tmp 92e5c89e4eSSatish Balay 93e5c89e4eSSatish Balay Environmental Variables: 94811af0c4SBarry Smith + `PETSC_SHARED_TMP` - indicates the directory is shared among the MPI ranks 95811af0c4SBarry Smith . `PETSC_NOT_SHARED_TMP` - indicates the directory is not shared among the MPI ranks 96811af0c4SBarry Smith - `PETSC_TMP` - name of the directory you wish to use as /tmp 97e5c89e4eSSatish Balay 98e5c89e4eSSatish Balay Level: developer 99e5c89e4eSSatish Balay 100e5c89e4eSSatish Balay Notes: 101e5c89e4eSSatish Balay Stores the status as a MPI attribute so it does not have 102e5c89e4eSSatish Balay to be redetermined each time. 103e5c89e4eSSatish Balay 104e5c89e4eSSatish Balay Assumes that all processors in a communicator either 105e5c89e4eSSatish Balay 1) have a common /tmp or 106a8c7a070SBarry Smith 2) each has a separate /tmp 107e5c89e4eSSatish Balay eventually we can write a fancier one that determines which processors 108e5c89e4eSSatish Balay share a common /tmp. 109e5c89e4eSSatish Balay 110e5c89e4eSSatish Balay This will be very slow on runs with a large number of processors since 111e5c89e4eSSatish Balay it requires O(p*p) file opens. 112e5c89e4eSSatish Balay 113*bfbbc7b7SBarry Smith If the environmental variable `PETSC_TMP` is set it will use this directory 114e5c89e4eSSatish Balay as the "/tmp" directory. 115e5c89e4eSSatish Balay 116811af0c4SBarry Smith .seealso: `PetscGetTmp()`, `PetscSharedWorkingDirectory()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 117e5c89e4eSSatish Balay @*/ 118d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSharedTmp(MPI_Comm comm, PetscBool *shared) 119d71ae5a4SJacob Faibussowitsch { 120e5c89e4eSSatish Balay PetscMPIInt size, rank, *tagvalp, sum, cnt, i; 121ace3abfcSBarry Smith PetscBool flg, iflg; 122e5c89e4eSSatish Balay FILE *fd; 123ed9cf6e9SBarry Smith int err; 124e5c89e4eSSatish Balay 125e5c89e4eSSatish Balay PetscFunctionBegin; 1269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 127e5c89e4eSSatish Balay if (size == 1) { 128e5c89e4eSSatish Balay *shared = PETSC_TRUE; 1293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 130e5c89e4eSSatish Balay } 131e5c89e4eSSatish Balay 1329566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_TMP", NULL, 0, &flg)); 133e5c89e4eSSatish Balay if (flg) { 134e5c89e4eSSatish Balay *shared = PETSC_TRUE; 1353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 136e5c89e4eSSatish Balay } 137e5c89e4eSSatish Balay 1389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_TMP", NULL, 0, &flg)); 139e5c89e4eSSatish Balay if (flg) { 140e5c89e4eSSatish Balay *shared = PETSC_FALSE; 1413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 142e5c89e4eSSatish Balay } 143e5c89e4eSSatish Balay 1445ea2b939SDuncan Campbell if (Petsc_SharedTmp_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_SharedTmp_keyval, NULL)); 145e5c89e4eSSatish Balay 1465ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_SharedTmp_keyval, (void **)&tagvalp, (int *)&iflg)); 147e5c89e4eSSatish Balay if (!iflg) { 148e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN], tmpname[PETSC_MAX_PATH_LEN]; 149e5c89e4eSSatish Balay 150e5c89e4eSSatish Balay /* This communicator does not yet have a shared tmp attribute */ 1519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 1525ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_SharedTmp_keyval, tagvalp)); 153e5c89e4eSSatish Balay 1549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_TMP", tmpname, 238, &iflg)); 155e5c89e4eSSatish Balay if (!iflg) { 156c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(filename, "/tmp", sizeof(filename))); 157e5c89e4eSSatish Balay } else { 158c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(filename, tmpname, sizeof(filename))); 159e5c89e4eSSatish Balay } 160e5c89e4eSSatish Balay 161c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(filename, "/petsctestshared", sizeof(filename))); 1629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 163e5c89e4eSSatish Balay 164e5c89e4eSSatish Balay /* each processor creates a /tmp file and all the later ones check */ 165e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 166e5c89e4eSSatish Balay *shared = PETSC_FALSE; 167e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 168e5c89e4eSSatish Balay if (rank == i) { 169e5c89e4eSSatish Balay fd = fopen(filename, "w"); 17028b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 171ed9cf6e9SBarry Smith err = fclose(fd); 17228b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 173e5c89e4eSSatish Balay } 1749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 175e5c89e4eSSatish Balay if (rank >= i) { 176e5c89e4eSSatish Balay fd = fopen(filename, "r"); 177a297a907SKarl Rupp if (fd) cnt = 1; 178a297a907SKarl Rupp else cnt = 0; 179e5c89e4eSSatish Balay if (fd) { 180ed9cf6e9SBarry Smith err = fclose(fd); 18128b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 182e5c89e4eSSatish Balay } 183a297a907SKarl Rupp } else cnt = 0; 184a297a907SKarl Rupp 1851c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 186a297a907SKarl Rupp if (rank == i) unlink(filename); 187e5c89e4eSSatish Balay 188e5c89e4eSSatish Balay if (sum == size) { 189e5c89e4eSSatish Balay *shared = PETSC_TRUE; 190e5c89e4eSSatish Balay break; 19108401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share /tmp "); 192e5c89e4eSSatish Balay } 193e5c89e4eSSatish Balay *tagvalp = (int)*shared; 1949566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "processors %s %s\n", (*shared) ? "share" : "do NOT share", (iflg ? tmpname : "/tmp"))); 195a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 1963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 197e5c89e4eSSatish Balay } 198e5c89e4eSSatish Balay 199e5c89e4eSSatish Balay /*@C 200f1a722f8SMatthew G. Knepley PetscSharedWorkingDirectory - Determines if all processors in a communicator share a working directory or have different ones. 201e5c89e4eSSatish Balay 202d083f849SBarry Smith Collective 203e5c89e4eSSatish Balay 2046b867d5aSJose E. Roman Input Parameter: 205e5c89e4eSSatish Balay . comm - MPI_Communicator that may share working directory 206e5c89e4eSSatish Balay 2076b867d5aSJose E. Roman Output Parameter: 208811af0c4SBarry Smith . shared - `PETSC_TRUE` or `PETSC_FALSE` 209e5c89e4eSSatish Balay 210e5c89e4eSSatish Balay Options Database Keys: 21110699b91SBarry Smith + -shared_working_directory - indicates the directory is shared among the MPI ranks 21210699b91SBarry Smith - -not_shared_working_directory - indicates the directory is shared among the MPI ranks 213e5c89e4eSSatish Balay 214e5c89e4eSSatish Balay Environmental Variables: 215811af0c4SBarry Smith + `PETSC_SHARED_WORKING_DIRECTORY` - indicates the directory is shared among the MPI ranks 216811af0c4SBarry Smith - `PETSC_NOT_SHARED_WORKING_DIRECTORY` - indicates the directory is shared among the MPI ranks 217e5c89e4eSSatish Balay 218e5c89e4eSSatish Balay Level: developer 219e5c89e4eSSatish Balay 220e5c89e4eSSatish Balay Notes: 221f1a722f8SMatthew G. Knepley Stores the status as a MPI attribute so it does not have to be redetermined each time. 222e5c89e4eSSatish Balay 223e5c89e4eSSatish Balay Assumes that all processors in a communicator either 224*bfbbc7b7SBarry Smith .vb 225*bfbbc7b7SBarry Smith 1) have a common working directory or 226*bfbbc7b7SBarry Smith 2) each has a separate working directory 227*bfbbc7b7SBarry Smith .ve 228f1a722f8SMatthew G. Knepley eventually we can write a fancier one that determines which processors share a common working directory. 229e5c89e4eSSatish Balay 230f1a722f8SMatthew G. Knepley This will be very slow on runs with a large number of processors since it requires O(p*p) file opens. 231811af0c4SBarry Smith 232811af0c4SBarry Smith .seealso: `PetscGetTmp()`, `PetscSharedTmp()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 233e5c89e4eSSatish Balay @*/ 234d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSharedWorkingDirectory(MPI_Comm comm, PetscBool *shared) 235d71ae5a4SJacob Faibussowitsch { 236e5c89e4eSSatish Balay PetscMPIInt size, rank, *tagvalp, sum, cnt, i; 237ace3abfcSBarry Smith PetscBool flg, iflg; 238e5c89e4eSSatish Balay FILE *fd; 239ed9cf6e9SBarry Smith int err; 240e5c89e4eSSatish Balay 241e5c89e4eSSatish Balay PetscFunctionBegin; 2429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 243e5c89e4eSSatish Balay if (size == 1) { 244e5c89e4eSSatish Balay *shared = PETSC_TRUE; 2453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 246e5c89e4eSSatish Balay } 247e5c89e4eSSatish Balay 2489566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 249e5c89e4eSSatish Balay if (flg) { 250e5c89e4eSSatish Balay *shared = PETSC_TRUE; 2513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 252e5c89e4eSSatish Balay } 253e5c89e4eSSatish Balay 2549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 255e5c89e4eSSatish Balay if (flg) { 256e5c89e4eSSatish Balay *shared = PETSC_FALSE; 2573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 258e5c89e4eSSatish Balay } 259e5c89e4eSSatish Balay 2605ea2b939SDuncan Campbell if (Petsc_SharedWD_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_SharedWD_keyval, NULL)); 261e5c89e4eSSatish Balay 2625ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_SharedWD_keyval, (void **)&tagvalp, (int *)&iflg)); 263e5c89e4eSSatish Balay if (!iflg) { 264e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN]; 265e5c89e4eSSatish Balay 266e5c89e4eSSatish Balay /* This communicator does not yet have a shared attribute */ 2679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 2685ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_SharedWD_keyval, tagvalp)); 269e5c89e4eSSatish Balay 2709566063dSJacob Faibussowitsch PetscCall(PetscGetWorkingDirectory(filename, 240)); 271c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(filename, "/petsctestshared", sizeof(filename))); 2729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 273e5c89e4eSSatish Balay 274e5c89e4eSSatish Balay /* each processor creates a file and all the later ones check */ 275e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 276e5c89e4eSSatish Balay *shared = PETSC_FALSE; 277e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 278e5c89e4eSSatish Balay if (rank == i) { 279e5c89e4eSSatish Balay fd = fopen(filename, "w"); 28028b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 281ed9cf6e9SBarry Smith err = fclose(fd); 28228b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 283e5c89e4eSSatish Balay } 2849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 285e5c89e4eSSatish Balay if (rank >= i) { 286e5c89e4eSSatish Balay fd = fopen(filename, "r"); 287a297a907SKarl Rupp if (fd) cnt = 1; 288a297a907SKarl Rupp else cnt = 0; 289e5c89e4eSSatish Balay if (fd) { 290ed9cf6e9SBarry Smith err = fclose(fd); 29128b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 292e5c89e4eSSatish Balay } 293a297a907SKarl Rupp } else cnt = 0; 294a297a907SKarl Rupp 2951c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 296a297a907SKarl Rupp if (rank == i) unlink(filename); 297e5c89e4eSSatish Balay 298e5c89e4eSSatish Balay if (sum == size) { 299e5c89e4eSSatish Balay *shared = PETSC_TRUE; 300e5c89e4eSSatish Balay break; 30108401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share working directory"); 302e5c89e4eSSatish Balay } 303e5c89e4eSSatish Balay *tagvalp = (int)*shared; 304a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 3059566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "processors %s working directory\n", (*shared) ? "shared" : "do NOT share")); 3063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 307e5c89e4eSSatish Balay } 308e5c89e4eSSatish Balay 309e5c89e4eSSatish Balay /*@C 310*bfbbc7b7SBarry Smith PetscFileRetrieve - Obtains a file from a URL or a compressed file 311e5c89e4eSSatish Balay and copies into local disk space as uncompressed. 312e5c89e4eSSatish Balay 313d083f849SBarry Smith Collective 314e5c89e4eSSatish Balay 315d8d19677SJose E. Roman Input Parameters: 3160c4f890aSBarry Smith + comm - processors accessing the file 3170c4f890aSBarry Smith . url - name of file, including entire URL (with or without .gz) 3180c4f890aSBarry Smith - llen - length of localname 319e5c89e4eSSatish Balay 320d8d19677SJose E. Roman Output Parameters: 32108fb59bfSBarry Smith + localname - name of local copy of file - valid on only process zero 32208fb59bfSBarry Smith - found - if found or retrieved the file - valid on all processes 323e5c89e4eSSatish Balay 3242fe279fdSBarry Smith Level: intermediate 3252fe279fdSBarry Smith 326811af0c4SBarry Smith Note: 32795452b02SPatrick Sanan if the file already exists local this function just returns without downloading it. 328e5c89e4eSSatish Balay 329e5c89e4eSSatish Balay @*/ 330d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFileRetrieve(MPI_Comm comm, const char url[], char localname[], size_t llen, PetscBool *found) 331d71ae5a4SJacob Faibussowitsch { 332bbcf679cSJacob Faibussowitsch char buffer[PETSC_MAX_PATH_LEN], *par = NULL, *tlocalname = NULL, name[PETSC_MAX_PATH_LEN]; 333e5c89e4eSSatish Balay FILE *fp; 334e5c89e4eSSatish Balay PetscMPIInt rank; 335e5c89e4eSSatish Balay size_t len = 0; 33608fb59bfSBarry Smith PetscBool flg1, flg2, flg3, flg4, download, compressed = PETSC_FALSE; 337e5c89e4eSSatish Balay 338e5c89e4eSSatish Balay PetscFunctionBegin; 3399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 340dd400576SPatrick Sanan if (rank == 0) { 341e5c89e4eSSatish Balay *found = PETSC_FALSE; 342e5c89e4eSSatish Balay 3439566063dSJacob Faibussowitsch PetscCall(PetscStrstr(url, ".gz", &par)); 34408fb59bfSBarry Smith if (par) { 3459566063dSJacob Faibussowitsch PetscCall(PetscStrlen(par, &len)); 34608fb59bfSBarry Smith if (len == 3) compressed = PETSC_TRUE; 34708fb59bfSBarry Smith } 348e5c89e4eSSatish Balay 3499566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "ftp://", 6, &flg1)); 3509566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "http://", 7, &flg2)); 3519566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "file://", 7, &flg3)); 3529566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "https://", 8, &flg4)); 353a4772d12SBarry Smith download = (PetscBool)(flg1 || flg2 || flg3 || flg4); 35408fb59bfSBarry Smith 35508fb59bfSBarry Smith if (!download && !compressed) { 3569566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3579566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 358487e5849SBarry Smith if (*found) { 3599566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Found file %s\n", url)); 360487e5849SBarry Smith } else { 3619566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Did not find file %s\n", url)); 362487e5849SBarry Smith } 36308fb59bfSBarry Smith goto done; 364734f99bcSBarry Smith } 365734f99bcSBarry Smith 36605698389SBarry Smith /* look for uncompressed file in requested directory */ 36705698389SBarry Smith if (compressed) { 3689566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3699566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 37005698389SBarry Smith *par = 0; /* remove .gz extension */ 3719566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 37205698389SBarry Smith if (*found) goto done; 37305698389SBarry Smith } 37405698389SBarry Smith 37505698389SBarry Smith /* look for file in current directory */ 3769566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(url, '/', &tlocalname)); 3779566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 37808fb59bfSBarry Smith if (compressed) { 3799566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 38008fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 38108fb59bfSBarry Smith } 3829566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 38308fb59bfSBarry Smith if (*found) goto done; 384e5c89e4eSSatish Balay 38508fb59bfSBarry Smith if (download) { 38608fb59bfSBarry Smith /* local file is not already here so use curl to get it */ 3879566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 388c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(buffer, "curl --fail --silent --show-error ", sizeof(buffer))); 389c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, url, sizeof(buffer))); 390c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, " > ", sizeof(buffer))); 391c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, localname, sizeof(buffer))); 392e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN) 3939566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 3949566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 395e5c89e4eSSatish Balay #else 396e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 397e5c89e4eSSatish Balay #endif 3989566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 3996e3a5469SBarry Smith if (*found) { 4006e3a5469SBarry Smith FILE *fd; 4016e3a5469SBarry Smith char buf[1024], *str, *substring; 4026e3a5469SBarry Smith 4036e3a5469SBarry Smith /* check if the file didn't exist so it downloaded an HTML message instead */ 4046e3a5469SBarry Smith fd = fopen(localname, "r"); 40528b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscTestFile() indicates %s exists but fopen() cannot open it", localname); 4066e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4076e3a5469SBarry Smith while (str) { 4089566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "<!DOCTYPE html>", &substring)); 40928b400f6SJacob Faibussowitsch PetscCheck(!substring, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unable to download %s it does not appear to exist at this URL, dummy HTML file was downloaded", url); 4109566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "Not Found", &substring)); 41128b400f6SJacob Faibussowitsch PetscCheck(!substring, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unable to download %s it does not appear to exist at this URL, dummy HTML file was downloaded", url); 4126e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4136e3a5469SBarry Smith } 4146e3a5469SBarry Smith fclose(fd); 4156e3a5469SBarry Smith } 41608fb59bfSBarry Smith } else if (compressed) { 4179566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 41808fb59bfSBarry Smith if (!*found) goto done; 4199566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 42008fb59bfSBarry Smith } 42108fb59bfSBarry Smith if (compressed) { 4229566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(localname, '/', &tlocalname)); 4239566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, tlocalname, PETSC_MAX_PATH_LEN)); 4249566063dSJacob Faibussowitsch PetscCall(PetscStrstr(name, ".gz", &par)); 42508fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 42608fb59bfSBarry Smith /* uncompress file */ 427c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(buffer, "gzip -c -d ", sizeof(buffer))); 428c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, localname, sizeof(buffer))); 429c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, " > ", sizeof(buffer))); 430c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, name, sizeof(buffer))); 43108fb59bfSBarry Smith #if defined(PETSC_HAVE_POPEN) 4329566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 4339566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 43408fb59bfSBarry Smith #else 43508fb59bfSBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 43608fb59bfSBarry Smith #endif 4379566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, name, llen)); 4389566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 439e5c89e4eSSatish Balay } 440e5c89e4eSSatish Balay } 441955d42a0SBarry Smith done: 4429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(found, 1, MPIU_BOOL, 0, comm)); 4439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(localname, llen, MPI_CHAR, 0, comm)); 4443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 445e5c89e4eSSatish Balay } 446