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 22e5c89e4eSSatish Balay 23480cf27aSJed Brown /* 24480cf27aSJed Brown Private routine to delete tmp/shared storage 25480cf27aSJed Brown 26480cf27aSJed Brown This is called by MPI, not by users. 27480cf27aSJed Brown 2812801b39SBarry Smith Note: this is declared extern "C" because it is passed to MPI_Comm_create_keyval() 29480cf27aSJed Brown 30480cf27aSJed Brown */ 319371c9d4SSatish Balay PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelTmpShared(MPI_Comm comm, PetscMPIInt keyval, void *count_val, void *extra_state) { 32480cf27aSJed Brown PetscFunctionBegin; 339566063dSJacob Faibussowitsch PetscCallMPI(PetscInfo(NULL, "Deleting tmp/shared data in an MPI_Comm %ld\n", (long)comm)); 349566063dSJacob Faibussowitsch PetscCallMPI(PetscFree(count_val)); 35480cf27aSJed Brown PetscFunctionReturn(MPI_SUCCESS); 36480cf27aSJed Brown } 37e5c89e4eSSatish Balay 38e5c89e4eSSatish Balay /*@C 39e5c89e4eSSatish Balay PetscGetTmp - Gets the name of the tmp directory 40e5c89e4eSSatish Balay 41d083f849SBarry Smith Collective 42e5c89e4eSSatish Balay 43e5c89e4eSSatish Balay Input Parameters: 44e5c89e4eSSatish Balay + comm - MPI_Communicator that may share /tmp 45e5c89e4eSSatish Balay - len - length of string to hold name 46e5c89e4eSSatish Balay 47f899ff85SJose E. Roman Output Parameter: 48e5c89e4eSSatish Balay . dir - directory name 49e5c89e4eSSatish Balay 50e5c89e4eSSatish Balay Options Database Keys: 5110699b91SBarry Smith + -shared_tmp - indicates the directory is shared among the MPI ranks 5210699b91SBarry Smith . -not_shared_tmp - indicates the directory is not shared among the MPI ranks 5310699b91SBarry Smith - -tmp tmpdir - name of the directory you wish to use as /tmp 54e5c89e4eSSatish Balay 55e5c89e4eSSatish Balay Environmental Variables: 56*811af0c4SBarry Smith + `PETSC_SHARED_TMP` - indicates the directory is shared among the MPI ranks 57*811af0c4SBarry Smith . `PETSC_NOT_SHARED_TMP` - indicates the directory is not shared among the MPI ranks 58*811af0c4SBarry Smith - `PETSC_TMP` - name of the directory you wish to use as /tmp 59e5c89e4eSSatish Balay 60e5c89e4eSSatish Balay Level: developer 61e5c89e4eSSatish Balay 62*811af0c4SBarry Smith .seealso: `PetscSharedTmp()`, `PetscSharedWorkingDirectory()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 63e5c89e4eSSatish Balay @*/ 649371c9d4SSatish Balay PetscErrorCode PetscGetTmp(MPI_Comm comm, char dir[], size_t len) { 65ace3abfcSBarry Smith PetscBool flg; 66e5c89e4eSSatish Balay 67e5c89e4eSSatish Balay PetscFunctionBegin; 689566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_TMP", dir, len, &flg)); 6948a46eb9SPierre Jolivet if (!flg) PetscCall(PetscStrncpy(dir, "/tmp", len)); 70e5c89e4eSSatish Balay PetscFunctionReturn(0); 71e5c89e4eSSatish Balay } 72e5c89e4eSSatish Balay 73e5c89e4eSSatish Balay /*@C 74e5c89e4eSSatish Balay PetscSharedTmp - Determines if all processors in a communicator share a 75e5c89e4eSSatish Balay /tmp or have different ones. 76e5c89e4eSSatish Balay 77d083f849SBarry Smith Collective 78e5c89e4eSSatish Balay 79*811af0c4SBarry Smith Input Parameter: 80e5c89e4eSSatish Balay . comm - MPI_Communicator that may share /tmp 81e5c89e4eSSatish Balay 82*811af0c4SBarry Smith Output Parameter: 83*811af0c4SBarry Smith . shared - `PETSC_TRUE` or `PETSC_FALSE` 84e5c89e4eSSatish Balay 85e5c89e4eSSatish Balay Options Database Keys: 8610699b91SBarry Smith + -shared_tmp - indicates the directory is shared among the MPI ranks 8710699b91SBarry Smith . -not_shared_tmp - indicates the directory is not shared among the MPI ranks 8810699b91SBarry Smith - -tmp tmpdir - name of the directory you wish to use as /tmp 89e5c89e4eSSatish Balay 90e5c89e4eSSatish Balay Environmental Variables: 91*811af0c4SBarry Smith + `PETSC_SHARED_TMP` - indicates the directory is shared among the MPI ranks 92*811af0c4SBarry Smith . `PETSC_NOT_SHARED_TMP` - indicates the directory is not shared among the MPI ranks 93*811af0c4SBarry Smith - `PETSC_TMP` - name of the directory you wish to use as /tmp 94e5c89e4eSSatish Balay 95e5c89e4eSSatish Balay Level: developer 96e5c89e4eSSatish Balay 97e5c89e4eSSatish Balay Notes: 98e5c89e4eSSatish Balay Stores the status as a MPI attribute so it does not have 99e5c89e4eSSatish Balay to be redetermined each time. 100e5c89e4eSSatish Balay 101e5c89e4eSSatish Balay Assumes that all processors in a communicator either 102e5c89e4eSSatish Balay 1) have a common /tmp or 103a8c7a070SBarry Smith 2) each has a separate /tmp 104e5c89e4eSSatish Balay eventually we can write a fancier one that determines which processors 105e5c89e4eSSatish Balay share a common /tmp. 106e5c89e4eSSatish Balay 107e5c89e4eSSatish Balay This will be very slow on runs with a large number of processors since 108e5c89e4eSSatish Balay it requires O(p*p) file opens. 109e5c89e4eSSatish Balay 110e5c89e4eSSatish Balay If the environmental variable PETSC_TMP is set it will use this directory 111e5c89e4eSSatish Balay as the "/tmp" directory. 112e5c89e4eSSatish Balay 113*811af0c4SBarry Smith .seealso: `PetscGetTmp()`, `PetscSharedWorkingDirectory()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 114e5c89e4eSSatish Balay @*/ 1159371c9d4SSatish Balay PetscErrorCode PetscSharedTmp(MPI_Comm comm, PetscBool *shared) { 116e5c89e4eSSatish Balay PetscMPIInt size, rank, *tagvalp, sum, cnt, i; 117ace3abfcSBarry Smith PetscBool flg, iflg; 118e5c89e4eSSatish Balay FILE *fd; 119e5c89e4eSSatish Balay static PetscMPIInt Petsc_Tmp_keyval = MPI_KEYVAL_INVALID; 120ed9cf6e9SBarry Smith int err; 121e5c89e4eSSatish Balay 122e5c89e4eSSatish Balay PetscFunctionBegin; 1239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 124e5c89e4eSSatish Balay if (size == 1) { 125e5c89e4eSSatish Balay *shared = PETSC_TRUE; 126e5c89e4eSSatish Balay PetscFunctionReturn(0); 127e5c89e4eSSatish Balay } 128e5c89e4eSSatish Balay 1299566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_TMP", NULL, 0, &flg)); 130e5c89e4eSSatish Balay if (flg) { 131e5c89e4eSSatish Balay *shared = PETSC_TRUE; 132e5c89e4eSSatish Balay PetscFunctionReturn(0); 133e5c89e4eSSatish Balay } 134e5c89e4eSSatish Balay 1359566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_TMP", NULL, 0, &flg)); 136e5c89e4eSSatish Balay if (flg) { 137e5c89e4eSSatish Balay *shared = PETSC_FALSE; 138e5c89e4eSSatish Balay PetscFunctionReturn(0); 139e5c89e4eSSatish Balay } 140e5c89e4eSSatish Balay 14148a46eb9SPierre Jolivet if (Petsc_Tmp_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_Tmp_keyval, NULL)); 142e5c89e4eSSatish Balay 1439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Tmp_keyval, (void **)&tagvalp, (int *)&iflg)); 144e5c89e4eSSatish Balay if (!iflg) { 145e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN], tmpname[PETSC_MAX_PATH_LEN]; 146e5c89e4eSSatish Balay 147e5c89e4eSSatish Balay /* This communicator does not yet have a shared tmp attribute */ 1489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 1499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Tmp_keyval, tagvalp)); 150e5c89e4eSSatish Balay 1519566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_TMP", tmpname, 238, &iflg)); 152e5c89e4eSSatish Balay if (!iflg) { 1539566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(filename, "/tmp")); 154e5c89e4eSSatish Balay } else { 1559566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(filename, tmpname)); 156e5c89e4eSSatish Balay } 157e5c89e4eSSatish Balay 1589566063dSJacob Faibussowitsch PetscCall(PetscStrcat(filename, "/petsctestshared")); 1599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 160e5c89e4eSSatish Balay 161e5c89e4eSSatish Balay /* each processor creates a /tmp file and all the later ones check */ 162e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 163e5c89e4eSSatish Balay *shared = PETSC_FALSE; 164e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 165e5c89e4eSSatish Balay if (rank == i) { 166e5c89e4eSSatish Balay fd = fopen(filename, "w"); 16728b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 168ed9cf6e9SBarry Smith err = fclose(fd); 16928b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 170e5c89e4eSSatish Balay } 1719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 172e5c89e4eSSatish Balay if (rank >= i) { 173e5c89e4eSSatish Balay fd = fopen(filename, "r"); 174a297a907SKarl Rupp if (fd) cnt = 1; 175a297a907SKarl Rupp else cnt = 0; 176e5c89e4eSSatish Balay if (fd) { 177ed9cf6e9SBarry Smith err = fclose(fd); 17828b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 179e5c89e4eSSatish Balay } 180a297a907SKarl Rupp } else cnt = 0; 181a297a907SKarl Rupp 1821c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 183a297a907SKarl Rupp if (rank == i) unlink(filename); 184e5c89e4eSSatish Balay 185e5c89e4eSSatish Balay if (sum == size) { 186e5c89e4eSSatish Balay *shared = PETSC_TRUE; 187e5c89e4eSSatish Balay break; 18808401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share /tmp "); 189e5c89e4eSSatish Balay } 190e5c89e4eSSatish Balay *tagvalp = (int)*shared; 1919566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "processors %s %s\n", (*shared) ? "share" : "do NOT share", (iflg ? tmpname : "/tmp"))); 192a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 193e5c89e4eSSatish Balay PetscFunctionReturn(0); 194e5c89e4eSSatish Balay } 195e5c89e4eSSatish Balay 196e5c89e4eSSatish Balay /*@C 197f1a722f8SMatthew G. Knepley PetscSharedWorkingDirectory - Determines if all processors in a communicator share a working directory or have different ones. 198e5c89e4eSSatish Balay 199d083f849SBarry Smith Collective 200e5c89e4eSSatish Balay 2016b867d5aSJose E. Roman Input Parameter: 202e5c89e4eSSatish Balay . comm - MPI_Communicator that may share working directory 203e5c89e4eSSatish Balay 2046b867d5aSJose E. Roman Output Parameter: 205*811af0c4SBarry Smith . shared - `PETSC_TRUE` or `PETSC_FALSE` 206e5c89e4eSSatish Balay 207e5c89e4eSSatish Balay Options Database Keys: 20810699b91SBarry Smith + -shared_working_directory - indicates the directory is shared among the MPI ranks 20910699b91SBarry Smith - -not_shared_working_directory - indicates the directory is shared among the MPI ranks 210e5c89e4eSSatish Balay 211e5c89e4eSSatish Balay Environmental Variables: 212*811af0c4SBarry Smith + `PETSC_SHARED_WORKING_DIRECTORY` - indicates the directory is shared among the MPI ranks 213*811af0c4SBarry Smith - `PETSC_NOT_SHARED_WORKING_DIRECTORY` - indicates the directory is shared among the MPI ranks 214e5c89e4eSSatish Balay 215e5c89e4eSSatish Balay Level: developer 216e5c89e4eSSatish Balay 217e5c89e4eSSatish Balay Notes: 218f1a722f8SMatthew G. Knepley Stores the status as a MPI attribute so it does not have to be redetermined each time. 219e5c89e4eSSatish Balay 220e5c89e4eSSatish Balay Assumes that all processors in a communicator either 221f1a722f8SMatthew G. Knepley $ 1) have a common working directory or 222f1a722f8SMatthew G. Knepley $ 2) each has a separate working directory 223f1a722f8SMatthew G. Knepley eventually we can write a fancier one that determines which processors share a common working directory. 224e5c89e4eSSatish Balay 225f1a722f8SMatthew G. Knepley This will be very slow on runs with a large number of processors since it requires O(p*p) file opens. 226*811af0c4SBarry Smith 227*811af0c4SBarry Smith .seealso: `PetscGetTmp()`, `PetscSharedTmp()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 228e5c89e4eSSatish Balay @*/ 2299371c9d4SSatish Balay PetscErrorCode PetscSharedWorkingDirectory(MPI_Comm comm, PetscBool *shared) { 230e5c89e4eSSatish Balay PetscMPIInt size, rank, *tagvalp, sum, cnt, i; 231ace3abfcSBarry Smith PetscBool flg, iflg; 232e5c89e4eSSatish Balay FILE *fd; 233e5c89e4eSSatish Balay static PetscMPIInt Petsc_WD_keyval = MPI_KEYVAL_INVALID; 234ed9cf6e9SBarry Smith int err; 235e5c89e4eSSatish Balay 236e5c89e4eSSatish Balay PetscFunctionBegin; 2379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 238e5c89e4eSSatish Balay if (size == 1) { 239e5c89e4eSSatish Balay *shared = PETSC_TRUE; 240e5c89e4eSSatish Balay PetscFunctionReturn(0); 241e5c89e4eSSatish Balay } 242e5c89e4eSSatish Balay 2439566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 244e5c89e4eSSatish Balay if (flg) { 245e5c89e4eSSatish Balay *shared = PETSC_TRUE; 246e5c89e4eSSatish Balay PetscFunctionReturn(0); 247e5c89e4eSSatish Balay } 248e5c89e4eSSatish Balay 2499566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 250e5c89e4eSSatish Balay if (flg) { 251e5c89e4eSSatish Balay *shared = PETSC_FALSE; 252e5c89e4eSSatish Balay PetscFunctionReturn(0); 253e5c89e4eSSatish Balay } 254e5c89e4eSSatish Balay 25548a46eb9SPierre Jolivet if (Petsc_WD_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_WD_keyval, NULL)); 256e5c89e4eSSatish Balay 2579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_WD_keyval, (void **)&tagvalp, (int *)&iflg)); 258e5c89e4eSSatish Balay if (!iflg) { 259e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN]; 260e5c89e4eSSatish Balay 261e5c89e4eSSatish Balay /* This communicator does not yet have a shared attribute */ 2629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 2639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_WD_keyval, tagvalp)); 264e5c89e4eSSatish Balay 2659566063dSJacob Faibussowitsch PetscCall(PetscGetWorkingDirectory(filename, 240)); 2669566063dSJacob Faibussowitsch PetscCall(PetscStrcat(filename, "/petsctestshared")); 2679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 268e5c89e4eSSatish Balay 269e5c89e4eSSatish Balay /* each processor creates a file and all the later ones check */ 270e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 271e5c89e4eSSatish Balay *shared = PETSC_FALSE; 272e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 273e5c89e4eSSatish Balay if (rank == i) { 274e5c89e4eSSatish Balay fd = fopen(filename, "w"); 27528b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 276ed9cf6e9SBarry Smith err = fclose(fd); 27728b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 278e5c89e4eSSatish Balay } 2799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 280e5c89e4eSSatish Balay if (rank >= i) { 281e5c89e4eSSatish Balay fd = fopen(filename, "r"); 282a297a907SKarl Rupp if (fd) cnt = 1; 283a297a907SKarl Rupp else cnt = 0; 284e5c89e4eSSatish Balay if (fd) { 285ed9cf6e9SBarry Smith err = fclose(fd); 28628b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 287e5c89e4eSSatish Balay } 288a297a907SKarl Rupp } else cnt = 0; 289a297a907SKarl Rupp 2901c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 291a297a907SKarl Rupp if (rank == i) unlink(filename); 292e5c89e4eSSatish Balay 293e5c89e4eSSatish Balay if (sum == size) { 294e5c89e4eSSatish Balay *shared = PETSC_TRUE; 295e5c89e4eSSatish Balay break; 29608401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share working directory"); 297e5c89e4eSSatish Balay } 298e5c89e4eSSatish Balay *tagvalp = (int)*shared; 299a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 3009566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "processors %s working directory\n", (*shared) ? "shared" : "do NOT share")); 301e5c89e4eSSatish Balay PetscFunctionReturn(0); 302e5c89e4eSSatish Balay } 303e5c89e4eSSatish Balay 304e5c89e4eSSatish Balay /*@C 3050c4f890aSBarry Smith PetscFileRetrieve - Obtains a file from a URL or compressed 306e5c89e4eSSatish Balay and copies into local disk space as uncompressed. 307e5c89e4eSSatish Balay 308d083f849SBarry Smith Collective 309e5c89e4eSSatish Balay 310d8d19677SJose E. Roman Input Parameters: 3110c4f890aSBarry Smith + comm - processors accessing the file 3120c4f890aSBarry Smith . url - name of file, including entire URL (with or without .gz) 3130c4f890aSBarry Smith - llen - length of localname 314e5c89e4eSSatish Balay 315d8d19677SJose E. Roman Output Parameters: 31608fb59bfSBarry Smith + localname - name of local copy of file - valid on only process zero 31708fb59bfSBarry Smith - found - if found or retrieved the file - valid on all processes 318e5c89e4eSSatish Balay 319*811af0c4SBarry Smith Note: 32095452b02SPatrick Sanan if the file already exists local this function just returns without downloading it. 321e5c89e4eSSatish Balay 3220c4f890aSBarry Smith Level: intermediate 323e5c89e4eSSatish Balay @*/ 3249371c9d4SSatish Balay PetscErrorCode PetscFileRetrieve(MPI_Comm comm, const char url[], char localname[], size_t llen, PetscBool *found) { 32508fb59bfSBarry Smith char buffer[PETSC_MAX_PATH_LEN], *par, *tlocalname, name[PETSC_MAX_PATH_LEN]; 326e5c89e4eSSatish Balay FILE *fp; 327e5c89e4eSSatish Balay PetscMPIInt rank; 328e5c89e4eSSatish Balay size_t len = 0; 32908fb59bfSBarry Smith PetscBool flg1, flg2, flg3, flg4, download, compressed = PETSC_FALSE; 330e5c89e4eSSatish Balay 331e5c89e4eSSatish Balay PetscFunctionBegin; 3329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 333dd400576SPatrick Sanan if (rank == 0) { 334e5c89e4eSSatish Balay *found = PETSC_FALSE; 335e5c89e4eSSatish Balay 3369566063dSJacob Faibussowitsch PetscCall(PetscStrstr(url, ".gz", &par)); 33708fb59bfSBarry Smith if (par) { 3389566063dSJacob Faibussowitsch PetscCall(PetscStrlen(par, &len)); 33908fb59bfSBarry Smith if (len == 3) compressed = PETSC_TRUE; 34008fb59bfSBarry Smith } 341e5c89e4eSSatish Balay 3429566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "ftp://", 6, &flg1)); 3439566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "http://", 7, &flg2)); 3449566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "file://", 7, &flg3)); 3459566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "https://", 8, &flg4)); 346a4772d12SBarry Smith download = (PetscBool)(flg1 || flg2 || flg3 || flg4); 34708fb59bfSBarry Smith 34808fb59bfSBarry Smith if (!download && !compressed) { 3499566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3509566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 351487e5849SBarry Smith if (*found) { 3529566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Found file %s\n", url)); 353487e5849SBarry Smith } else { 3549566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Did not find file %s\n", url)); 355487e5849SBarry Smith } 35608fb59bfSBarry Smith goto done; 357734f99bcSBarry Smith } 358734f99bcSBarry Smith 35905698389SBarry Smith /* look for uncompressed file in requested directory */ 36005698389SBarry Smith if (compressed) { 3619566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3629566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 36305698389SBarry Smith *par = 0; /* remove .gz extension */ 3649566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 36505698389SBarry Smith if (*found) goto done; 36605698389SBarry Smith } 36705698389SBarry Smith 36805698389SBarry Smith /* look for file in current directory */ 3699566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(url, '/', &tlocalname)); 3709566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 37108fb59bfSBarry Smith if (compressed) { 3729566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 37308fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 37408fb59bfSBarry Smith } 3759566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 37608fb59bfSBarry Smith if (*found) goto done; 377e5c89e4eSSatish Balay 37808fb59bfSBarry Smith if (download) { 37908fb59bfSBarry Smith /* local file is not already here so use curl to get it */ 3809566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 3819566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(buffer, "curl --fail --silent --show-error ")); 3829566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buffer, url)); 3839566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buffer, " > ")); 3849566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buffer, localname)); 385e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN) 3869566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 3879566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 388e5c89e4eSSatish Balay #else 389e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 390e5c89e4eSSatish Balay #endif 3919566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 3926e3a5469SBarry Smith if (*found) { 3936e3a5469SBarry Smith FILE *fd; 3946e3a5469SBarry Smith char buf[1024], *str, *substring; 3956e3a5469SBarry Smith 3966e3a5469SBarry Smith /* check if the file didn't exist so it downloaded an HTML message instead */ 3976e3a5469SBarry Smith fd = fopen(localname, "r"); 39828b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscTestFile() indicates %s exists but fopen() cannot open it", localname); 3996e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4006e3a5469SBarry Smith while (str) { 4019566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "<!DOCTYPE html>", &substring)); 40228b400f6SJacob 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); 4039566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "Not Found", &substring)); 40428b400f6SJacob 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); 4056e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4066e3a5469SBarry Smith } 4076e3a5469SBarry Smith fclose(fd); 4086e3a5469SBarry Smith } 40908fb59bfSBarry Smith } else if (compressed) { 4109566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 41108fb59bfSBarry Smith if (!*found) goto done; 4129566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 41308fb59bfSBarry Smith } 41408fb59bfSBarry Smith if (compressed) { 4159566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(localname, '/', &tlocalname)); 4169566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, tlocalname, PETSC_MAX_PATH_LEN)); 4179566063dSJacob Faibussowitsch PetscCall(PetscStrstr(name, ".gz", &par)); 41808fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 41908fb59bfSBarry Smith /* uncompress file */ 4209566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(buffer, "gzip -c -d ")); 4219566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buffer, localname)); 4229566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buffer, " > ")); 4239566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buffer, name)); 42408fb59bfSBarry Smith #if defined(PETSC_HAVE_POPEN) 4259566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 4269566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 42708fb59bfSBarry Smith #else 42808fb59bfSBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 42908fb59bfSBarry Smith #endif 4309566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, name, llen)); 4319566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 432e5c89e4eSSatish Balay } 433e5c89e4eSSatish Balay } 434955d42a0SBarry Smith done: 4359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(found, 1, MPIU_BOOL, 0, comm)); 4369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(localname, llen, MPI_CHAR, 0, comm)); 437e5c89e4eSSatish Balay PetscFunctionReturn(0); 438e5c89e4eSSatish Balay } 439