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 22*5ea2b939SDuncan 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 113e5c89e4eSSatish Balay 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 144*5ea2b939SDuncan 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 146*5ea2b939SDuncan 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)); 152*5ea2b939SDuncan 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 224f1a722f8SMatthew G. Knepley $ 1) have a common working directory or 225f1a722f8SMatthew G. Knepley $ 2) each has a separate working directory 226f1a722f8SMatthew G. Knepley eventually we can write a fancier one that determines which processors share a common working directory. 227e5c89e4eSSatish Balay 228f1a722f8SMatthew G. Knepley This will be very slow on runs with a large number of processors since it requires O(p*p) file opens. 229811af0c4SBarry Smith 230811af0c4SBarry Smith .seealso: `PetscGetTmp()`, `PetscSharedTmp()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 231e5c89e4eSSatish Balay @*/ 232d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSharedWorkingDirectory(MPI_Comm comm, PetscBool *shared) 233d71ae5a4SJacob Faibussowitsch { 234e5c89e4eSSatish Balay PetscMPIInt size, rank, *tagvalp, sum, cnt, i; 235ace3abfcSBarry Smith PetscBool flg, iflg; 236e5c89e4eSSatish Balay FILE *fd; 237ed9cf6e9SBarry Smith int err; 238e5c89e4eSSatish Balay 239e5c89e4eSSatish Balay PetscFunctionBegin; 2409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 241e5c89e4eSSatish Balay if (size == 1) { 242e5c89e4eSSatish Balay *shared = PETSC_TRUE; 2433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 244e5c89e4eSSatish Balay } 245e5c89e4eSSatish Balay 2469566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 247e5c89e4eSSatish Balay if (flg) { 248e5c89e4eSSatish Balay *shared = PETSC_TRUE; 2493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 250e5c89e4eSSatish Balay } 251e5c89e4eSSatish Balay 2529566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 253e5c89e4eSSatish Balay if (flg) { 254e5c89e4eSSatish Balay *shared = PETSC_FALSE; 2553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 256e5c89e4eSSatish Balay } 257e5c89e4eSSatish Balay 258*5ea2b939SDuncan Campbell if (Petsc_SharedWD_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_SharedWD_keyval, NULL)); 259e5c89e4eSSatish Balay 260*5ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_SharedWD_keyval, (void **)&tagvalp, (int *)&iflg)); 261e5c89e4eSSatish Balay if (!iflg) { 262e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN]; 263e5c89e4eSSatish Balay 264e5c89e4eSSatish Balay /* This communicator does not yet have a shared attribute */ 2659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 266*5ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_SharedWD_keyval, tagvalp)); 267e5c89e4eSSatish Balay 2689566063dSJacob Faibussowitsch PetscCall(PetscGetWorkingDirectory(filename, 240)); 269c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(filename, "/petsctestshared", sizeof(filename))); 2709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 271e5c89e4eSSatish Balay 272e5c89e4eSSatish Balay /* each processor creates a file and all the later ones check */ 273e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 274e5c89e4eSSatish Balay *shared = PETSC_FALSE; 275e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 276e5c89e4eSSatish Balay if (rank == i) { 277e5c89e4eSSatish Balay fd = fopen(filename, "w"); 27828b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 279ed9cf6e9SBarry Smith err = fclose(fd); 28028b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 281e5c89e4eSSatish Balay } 2829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 283e5c89e4eSSatish Balay if (rank >= i) { 284e5c89e4eSSatish Balay fd = fopen(filename, "r"); 285a297a907SKarl Rupp if (fd) cnt = 1; 286a297a907SKarl Rupp else cnt = 0; 287e5c89e4eSSatish Balay if (fd) { 288ed9cf6e9SBarry Smith err = fclose(fd); 28928b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 290e5c89e4eSSatish Balay } 291a297a907SKarl Rupp } else cnt = 0; 292a297a907SKarl Rupp 2931c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 294a297a907SKarl Rupp if (rank == i) unlink(filename); 295e5c89e4eSSatish Balay 296e5c89e4eSSatish Balay if (sum == size) { 297e5c89e4eSSatish Balay *shared = PETSC_TRUE; 298e5c89e4eSSatish Balay break; 29908401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share working directory"); 300e5c89e4eSSatish Balay } 301e5c89e4eSSatish Balay *tagvalp = (int)*shared; 302a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 3039566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "processors %s working directory\n", (*shared) ? "shared" : "do NOT share")); 3043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 305e5c89e4eSSatish Balay } 306e5c89e4eSSatish Balay 307e5c89e4eSSatish Balay /*@C 3080c4f890aSBarry Smith PetscFileRetrieve - Obtains a file from a URL or compressed 309e5c89e4eSSatish Balay and copies into local disk space as uncompressed. 310e5c89e4eSSatish Balay 311d083f849SBarry Smith Collective 312e5c89e4eSSatish Balay 313d8d19677SJose E. Roman Input Parameters: 3140c4f890aSBarry Smith + comm - processors accessing the file 3150c4f890aSBarry Smith . url - name of file, including entire URL (with or without .gz) 3160c4f890aSBarry Smith - llen - length of localname 317e5c89e4eSSatish Balay 318d8d19677SJose E. Roman Output Parameters: 31908fb59bfSBarry Smith + localname - name of local copy of file - valid on only process zero 32008fb59bfSBarry Smith - found - if found or retrieved the file - valid on all processes 321e5c89e4eSSatish Balay 322811af0c4SBarry Smith Note: 32395452b02SPatrick Sanan if the file already exists local this function just returns without downloading it. 324e5c89e4eSSatish Balay 3250c4f890aSBarry Smith Level: intermediate 326e5c89e4eSSatish Balay @*/ 327d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFileRetrieve(MPI_Comm comm, const char url[], char localname[], size_t llen, PetscBool *found) 328d71ae5a4SJacob Faibussowitsch { 329bbcf679cSJacob Faibussowitsch char buffer[PETSC_MAX_PATH_LEN], *par = NULL, *tlocalname = NULL, name[PETSC_MAX_PATH_LEN]; 330e5c89e4eSSatish Balay FILE *fp; 331e5c89e4eSSatish Balay PetscMPIInt rank; 332e5c89e4eSSatish Balay size_t len = 0; 33308fb59bfSBarry Smith PetscBool flg1, flg2, flg3, flg4, download, compressed = PETSC_FALSE; 334e5c89e4eSSatish Balay 335e5c89e4eSSatish Balay PetscFunctionBegin; 3369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 337dd400576SPatrick Sanan if (rank == 0) { 338e5c89e4eSSatish Balay *found = PETSC_FALSE; 339e5c89e4eSSatish Balay 3409566063dSJacob Faibussowitsch PetscCall(PetscStrstr(url, ".gz", &par)); 34108fb59bfSBarry Smith if (par) { 3429566063dSJacob Faibussowitsch PetscCall(PetscStrlen(par, &len)); 34308fb59bfSBarry Smith if (len == 3) compressed = PETSC_TRUE; 34408fb59bfSBarry Smith } 345e5c89e4eSSatish Balay 3469566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "ftp://", 6, &flg1)); 3479566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "http://", 7, &flg2)); 3489566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "file://", 7, &flg3)); 3499566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "https://", 8, &flg4)); 350a4772d12SBarry Smith download = (PetscBool)(flg1 || flg2 || flg3 || flg4); 35108fb59bfSBarry Smith 35208fb59bfSBarry Smith if (!download && !compressed) { 3539566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3549566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 355487e5849SBarry Smith if (*found) { 3569566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Found file %s\n", url)); 357487e5849SBarry Smith } else { 3589566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Did not find file %s\n", url)); 359487e5849SBarry Smith } 36008fb59bfSBarry Smith goto done; 361734f99bcSBarry Smith } 362734f99bcSBarry Smith 36305698389SBarry Smith /* look for uncompressed file in requested directory */ 36405698389SBarry Smith if (compressed) { 3659566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3669566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 36705698389SBarry Smith *par = 0; /* remove .gz extension */ 3689566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 36905698389SBarry Smith if (*found) goto done; 37005698389SBarry Smith } 37105698389SBarry Smith 37205698389SBarry Smith /* look for file in current directory */ 3739566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(url, '/', &tlocalname)); 3749566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 37508fb59bfSBarry Smith if (compressed) { 3769566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 37708fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 37808fb59bfSBarry Smith } 3799566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 38008fb59bfSBarry Smith if (*found) goto done; 381e5c89e4eSSatish Balay 38208fb59bfSBarry Smith if (download) { 38308fb59bfSBarry Smith /* local file is not already here so use curl to get it */ 3849566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 385c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(buffer, "curl --fail --silent --show-error ", sizeof(buffer))); 386c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, url, sizeof(buffer))); 387c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, " > ", sizeof(buffer))); 388c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, localname, sizeof(buffer))); 389e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN) 3909566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 3919566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 392e5c89e4eSSatish Balay #else 393e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 394e5c89e4eSSatish Balay #endif 3959566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 3966e3a5469SBarry Smith if (*found) { 3976e3a5469SBarry Smith FILE *fd; 3986e3a5469SBarry Smith char buf[1024], *str, *substring; 3996e3a5469SBarry Smith 4006e3a5469SBarry Smith /* check if the file didn't exist so it downloaded an HTML message instead */ 4016e3a5469SBarry Smith fd = fopen(localname, "r"); 40228b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscTestFile() indicates %s exists but fopen() cannot open it", localname); 4036e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4046e3a5469SBarry Smith while (str) { 4059566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "<!DOCTYPE html>", &substring)); 40628b400f6SJacob 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); 4079566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "Not Found", &substring)); 40828b400f6SJacob 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); 4096e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4106e3a5469SBarry Smith } 4116e3a5469SBarry Smith fclose(fd); 4126e3a5469SBarry Smith } 41308fb59bfSBarry Smith } else if (compressed) { 4149566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 41508fb59bfSBarry Smith if (!*found) goto done; 4169566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 41708fb59bfSBarry Smith } 41808fb59bfSBarry Smith if (compressed) { 4199566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(localname, '/', &tlocalname)); 4209566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, tlocalname, PETSC_MAX_PATH_LEN)); 4219566063dSJacob Faibussowitsch PetscCall(PetscStrstr(name, ".gz", &par)); 42208fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 42308fb59bfSBarry Smith /* uncompress file */ 424c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(buffer, "gzip -c -d ", sizeof(buffer))); 425c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, localname, sizeof(buffer))); 426c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, " > ", sizeof(buffer))); 427c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, name, sizeof(buffer))); 42808fb59bfSBarry Smith #if defined(PETSC_HAVE_POPEN) 4299566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 4309566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 43108fb59bfSBarry Smith #else 43208fb59bfSBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 43308fb59bfSBarry Smith #endif 4349566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, name, llen)); 4359566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 436e5c89e4eSSatish Balay } 437e5c89e4eSSatish Balay } 438955d42a0SBarry Smith done: 4399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(found, 1, MPIU_BOOL, 0, comm)); 4409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(localname, llen, MPI_CHAR, 0, comm)); 4413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 442e5c89e4eSSatish Balay } 443