1e5c89e4eSSatish Balay /* 2e5c89e4eSSatish Balay Code for opening and closing files. 3e5c89e4eSSatish Balay */ 4c6db04a5SJed Brown #include <petscsys.h> 5e5c89e4eSSatish Balay #if defined(PETSC_HAVE_PWD_H) 6e5c89e4eSSatish Balay #include <pwd.h> 7e5c89e4eSSatish Balay #endif 8e5c89e4eSSatish Balay #include <ctype.h> 9e5c89e4eSSatish Balay #include <sys/stat.h> 10e5c89e4eSSatish Balay #if defined(PETSC_HAVE_UNISTD_H) 11e5c89e4eSSatish Balay #include <unistd.h> 12e5c89e4eSSatish Balay #endif 13e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SYS_UTSNAME_H) 14e5c89e4eSSatish Balay #include <sys/utsname.h> 15e5c89e4eSSatish Balay #endif 16e5c89e4eSSatish Balay #include <fcntl.h> 17e5c89e4eSSatish Balay #include <time.h> 18e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H) 19e5c89e4eSSatish Balay #include <sys/systeminfo.h> 20e5c89e4eSSatish Balay #endif 215ea2b939SDuncan Campbell #include <petsc/private/petscimpl.h> 22e5c89e4eSSatish Balay 23480cf27aSJed Brown /* 24480cf27aSJed Brown Private routine to delete tmp/shared storage 25480cf27aSJed Brown 2621532e8aSBarry Smith This is called by MPI, not by users, when communicator attributes are deleted 27480cf27aSJed Brown 28480cf27aSJed Brown */ 29*d6acfc2dSPierre Jolivet static PetscMPIInt MPIAPI Petsc_DelTmpShared(MPI_Comm comm, PetscMPIInt keyval, void *count_val, void *extra_state) 30d71ae5a4SJacob Faibussowitsch { 31480cf27aSJed Brown PetscFunctionBegin; 327c5b2466SBarry Smith PetscCallReturnMPI(PetscInfo(NULL, "Deleting tmp/shared data in an MPI_Comm %ld\n", (long)comm)); 337c5b2466SBarry Smith PetscCallReturnMPI(PetscFree(count_val)); 34480cf27aSJed Brown PetscFunctionReturn(MPI_SUCCESS); 35480cf27aSJed Brown } 36e5c89e4eSSatish Balay 3710450e9eSJacob Faibussowitsch // "Unknown section 'Environmental Variables'" 3810450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown 39e5c89e4eSSatish Balay /*@C 4021532e8aSBarry Smith PetscGetTmp - Gets the name of the "tmp" directory, often this is `/tmp` 41e5c89e4eSSatish Balay 42d083f849SBarry Smith Collective 43e5c89e4eSSatish Balay 44e5c89e4eSSatish Balay Input Parameters: 4521532e8aSBarry Smith + comm - MPI_Communicator that may share tmp 46e5c89e4eSSatish Balay - len - length of string to hold name 47e5c89e4eSSatish Balay 48f899ff85SJose E. Roman Output Parameter: 49e5c89e4eSSatish Balay . dir - directory name 50e5c89e4eSSatish Balay 51e5c89e4eSSatish Balay Options Database Keys: 5221532e8aSBarry Smith + -shared_tmp - indicates the directory is known to be shared among the MPI processes 5321532e8aSBarry Smith . -not_shared_tmp - indicates the directory is known to be not shared among the MPI processes 5421532e8aSBarry Smith - -tmp tmpdir - name of the directory you wish to use as tmp 55e5c89e4eSSatish Balay 56e5c89e4eSSatish Balay Environmental Variables: 5721532e8aSBarry Smith + `PETSC_SHARED_TMP` - indicates the directory is known to be shared among the MPI processes 5821532e8aSBarry Smith . `PETSC_NOT_SHARED_TMP` - indicates the directory is known to be not shared among the MPI processes 5921532e8aSBarry Smith - `PETSC_TMP` - name of the directory you wish to use as tmp 60e5c89e4eSSatish Balay 61e5c89e4eSSatish Balay Level: developer 62e5c89e4eSSatish Balay 63811af0c4SBarry Smith .seealso: `PetscSharedTmp()`, `PetscSharedWorkingDirectory()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 64e5c89e4eSSatish Balay @*/ 65d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGetTmp(MPI_Comm comm, char dir[], size_t len) 66d71ae5a4SJacob Faibussowitsch { 67ace3abfcSBarry Smith PetscBool flg; 68e5c89e4eSSatish Balay 69e5c89e4eSSatish Balay PetscFunctionBegin; 709566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_TMP", dir, len, &flg)); 7148a46eb9SPierre Jolivet if (!flg) PetscCall(PetscStrncpy(dir, "/tmp", len)); 723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 73e5c89e4eSSatish Balay } 74e5c89e4eSSatish Balay 7510450e9eSJacob Faibussowitsch // "Unknown section 'Environmental Variables'" 7610450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown 77cc4c1da9SBarry Smith /*@ 78e5c89e4eSSatish Balay PetscSharedTmp - Determines if all processors in a communicator share a 7921532e8aSBarry Smith tmp directory or have different ones. 80e5c89e4eSSatish Balay 81d083f849SBarry Smith Collective 82e5c89e4eSSatish Balay 83811af0c4SBarry Smith Input Parameter: 8421532e8aSBarry Smith . comm - MPI_Communicator that may share tmp 85e5c89e4eSSatish Balay 86811af0c4SBarry Smith Output Parameter: 87811af0c4SBarry Smith . shared - `PETSC_TRUE` or `PETSC_FALSE` 88e5c89e4eSSatish Balay 89e5c89e4eSSatish Balay Options Database Keys: 9021532e8aSBarry Smith + -shared_tmp - indicates the directory is known to be shared among the MPI processes 9121532e8aSBarry Smith . -not_shared_tmp - indicates the directory is known to be not shared among the MPI processes 9221532e8aSBarry Smith - -tmp tmpdir - name of the directory you wish to use as tmp 93e5c89e4eSSatish Balay 94e5c89e4eSSatish Balay Environmental Variables: 9521532e8aSBarry Smith + `PETSC_SHARED_TMP` - indicates the directory is known to be shared among the MPI processes 9621532e8aSBarry Smith . `PETSC_NOT_SHARED_TMP` - indicates the directory is known to be not shared among the MPI processes 9721532e8aSBarry Smith - `PETSC_TMP` - name of the directory you wish to use as tmp 98e5c89e4eSSatish Balay 99e5c89e4eSSatish Balay Level: developer 100e5c89e4eSSatish Balay 101e5c89e4eSSatish Balay Notes: 102e5c89e4eSSatish Balay Stores the status as a MPI attribute so it does not have 103e5c89e4eSSatish Balay to be redetermined each time. 104e5c89e4eSSatish Balay 105e5c89e4eSSatish Balay Assumes that all processors in a communicator either 10621532e8aSBarry Smith 1) have a common tmp or 10721532e8aSBarry Smith 2) each has a separate tmp 108e5c89e4eSSatish Balay eventually we can write a fancier one that determines which processors 10921532e8aSBarry Smith share a common tmp. 110e5c89e4eSSatish Balay 111e5c89e4eSSatish Balay This will be very slow on runs with a large number of processors since 112e5c89e4eSSatish Balay it requires O(p*p) file opens. 113e5c89e4eSSatish Balay 114bfbbc7b7SBarry Smith If the environmental variable `PETSC_TMP` is set it will use this directory 11521532e8aSBarry Smith as the "tmp" directory. 116e5c89e4eSSatish Balay 117811af0c4SBarry Smith .seealso: `PetscGetTmp()`, `PetscSharedWorkingDirectory()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 118e5c89e4eSSatish Balay @*/ 119d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSharedTmp(MPI_Comm comm, PetscBool *shared) 120d71ae5a4SJacob Faibussowitsch { 121e5c89e4eSSatish Balay PetscMPIInt size, rank, *tagvalp, sum, cnt, i; 122ace3abfcSBarry Smith PetscBool flg, iflg; 123e5c89e4eSSatish Balay FILE *fd; 124ed9cf6e9SBarry Smith int err; 125e5c89e4eSSatish Balay 126e5c89e4eSSatish Balay PetscFunctionBegin; 1279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 128e5c89e4eSSatish Balay if (size == 1) { 129e5c89e4eSSatish Balay *shared = PETSC_TRUE; 1303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 131e5c89e4eSSatish Balay } 132e5c89e4eSSatish Balay 1339566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_TMP", NULL, 0, &flg)); 134e5c89e4eSSatish Balay if (flg) { 135e5c89e4eSSatish Balay *shared = PETSC_TRUE; 1363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 137e5c89e4eSSatish Balay } 138e5c89e4eSSatish Balay 1399566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_TMP", NULL, 0, &flg)); 140e5c89e4eSSatish Balay if (flg) { 141e5c89e4eSSatish Balay *shared = PETSC_FALSE; 1423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 143e5c89e4eSSatish Balay } 144e5c89e4eSSatish Balay 1455ea2b939SDuncan Campbell if (Petsc_SharedTmp_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_SharedTmp_keyval, NULL)); 146e5c89e4eSSatish Balay 1475ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_SharedTmp_keyval, (void **)&tagvalp, (int *)&iflg)); 148e5c89e4eSSatish Balay if (!iflg) { 149e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN], tmpname[PETSC_MAX_PATH_LEN]; 150e5c89e4eSSatish Balay 151e5c89e4eSSatish Balay /* This communicator does not yet have a shared tmp attribute */ 1529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 1535ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_SharedTmp_keyval, tagvalp)); 154e5c89e4eSSatish Balay 1559566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_TMP", tmpname, 238, &iflg)); 156e5c89e4eSSatish Balay if (!iflg) { 157c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(filename, "/tmp", sizeof(filename))); 158e5c89e4eSSatish Balay } else { 159c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(filename, tmpname, sizeof(filename))); 160e5c89e4eSSatish Balay } 161e5c89e4eSSatish Balay 162c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(filename, "/petsctestshared", sizeof(filename))); 1639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 164e5c89e4eSSatish Balay 165e5c89e4eSSatish Balay /* each processor creates a /tmp file and all the later ones check */ 166e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 167e5c89e4eSSatish Balay *shared = PETSC_FALSE; 168e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 169e5c89e4eSSatish Balay if (rank == i) { 170e5c89e4eSSatish Balay fd = fopen(filename, "w"); 17128b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 172ed9cf6e9SBarry Smith err = fclose(fd); 17328b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 174e5c89e4eSSatish Balay } 1759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 176e5c89e4eSSatish Balay if (rank >= i) { 177e5c89e4eSSatish Balay fd = fopen(filename, "r"); 178a297a907SKarl Rupp if (fd) cnt = 1; 179a297a907SKarl Rupp else cnt = 0; 180e5c89e4eSSatish Balay if (fd) { 181ed9cf6e9SBarry Smith err = fclose(fd); 18228b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 183e5c89e4eSSatish Balay } 184a297a907SKarl Rupp } else cnt = 0; 185a297a907SKarl Rupp 186462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 187a297a907SKarl Rupp if (rank == i) unlink(filename); 188e5c89e4eSSatish Balay 189e5c89e4eSSatish Balay if (sum == size) { 190e5c89e4eSSatish Balay *shared = PETSC_TRUE; 191e5c89e4eSSatish Balay break; 19208401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share /tmp "); 193e5c89e4eSSatish Balay } 194e5c89e4eSSatish Balay *tagvalp = (int)*shared; 19557508eceSPierre Jolivet PetscCall(PetscInfo(NULL, "processors %s %s\n", *shared ? "share" : "do NOT share", iflg ? tmpname : "/tmp")); 196a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 1973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 198e5c89e4eSSatish Balay } 199e5c89e4eSSatish Balay 20010450e9eSJacob Faibussowitsch // "Unknown section 'Environmental Variables'" 20110450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown 202cc4c1da9SBarry Smith /*@ 203f1a722f8SMatthew G. Knepley PetscSharedWorkingDirectory - Determines if all processors in a communicator share a working directory or have different ones. 204e5c89e4eSSatish Balay 205d083f849SBarry Smith Collective 206e5c89e4eSSatish Balay 2076b867d5aSJose E. Roman Input Parameter: 208e5c89e4eSSatish Balay . comm - MPI_Communicator that may share working directory 209e5c89e4eSSatish Balay 2106b867d5aSJose E. Roman Output Parameter: 211811af0c4SBarry Smith . shared - `PETSC_TRUE` or `PETSC_FALSE` 212e5c89e4eSSatish Balay 213e5c89e4eSSatish Balay Options Database Keys: 21421532e8aSBarry Smith + -shared_working_directory - indicates the directory is known to be shared among the MPI processes 21521532e8aSBarry Smith - -not_shared_working_directory - indicates the directory is known to be not shared among the MPI processes 216e5c89e4eSSatish Balay 217e5c89e4eSSatish Balay Environmental Variables: 21821532e8aSBarry Smith + `PETSC_SHARED_WORKING_DIRECTORY` - indicates the directory is known to be shared among the MPI processes 21921532e8aSBarry Smith - `PETSC_NOT_SHARED_WORKING_DIRECTORY` - indicates the directory is known to be not shared among the MPI processes 220e5c89e4eSSatish Balay 221e5c89e4eSSatish Balay Level: developer 222e5c89e4eSSatish Balay 223e5c89e4eSSatish Balay Notes: 224f1a722f8SMatthew G. Knepley Stores the status as a MPI attribute so it does not have to be redetermined each time. 225e5c89e4eSSatish Balay 226e5c89e4eSSatish Balay Assumes that all processors in a communicator either 227bfbbc7b7SBarry Smith .vb 228bfbbc7b7SBarry Smith 1) have a common working directory or 229bfbbc7b7SBarry Smith 2) each has a separate working directory 230bfbbc7b7SBarry Smith .ve 231f1a722f8SMatthew G. Knepley eventually we can write a fancier one that determines which processors share a common working directory. 232e5c89e4eSSatish Balay 233f1a722f8SMatthew G. Knepley This will be very slow on runs with a large number of processors since it requires O(p*p) file opens. 234811af0c4SBarry Smith 235811af0c4SBarry Smith .seealso: `PetscGetTmp()`, `PetscSharedTmp()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 236e5c89e4eSSatish Balay @*/ 237d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSharedWorkingDirectory(MPI_Comm comm, PetscBool *shared) 238d71ae5a4SJacob Faibussowitsch { 239e5c89e4eSSatish Balay PetscMPIInt size, rank, *tagvalp, sum, cnt, i; 240ace3abfcSBarry Smith PetscBool flg, iflg; 241e5c89e4eSSatish Balay FILE *fd; 242ed9cf6e9SBarry Smith int err; 243e5c89e4eSSatish Balay 244e5c89e4eSSatish Balay PetscFunctionBegin; 2459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 246e5c89e4eSSatish Balay if (size == 1) { 247e5c89e4eSSatish Balay *shared = PETSC_TRUE; 2483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 249e5c89e4eSSatish Balay } 250e5c89e4eSSatish Balay 2519566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 252e5c89e4eSSatish Balay if (flg) { 253e5c89e4eSSatish Balay *shared = PETSC_TRUE; 2543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 255e5c89e4eSSatish Balay } 256e5c89e4eSSatish Balay 2579566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 258e5c89e4eSSatish Balay if (flg) { 259e5c89e4eSSatish Balay *shared = PETSC_FALSE; 2603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 261e5c89e4eSSatish Balay } 262e5c89e4eSSatish Balay 2635ea2b939SDuncan Campbell if (Petsc_SharedWD_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_SharedWD_keyval, NULL)); 264e5c89e4eSSatish Balay 2655ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_SharedWD_keyval, (void **)&tagvalp, (int *)&iflg)); 266e5c89e4eSSatish Balay if (!iflg) { 267e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN]; 268e5c89e4eSSatish Balay 269e5c89e4eSSatish Balay /* This communicator does not yet have a shared attribute */ 2709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 2715ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_SharedWD_keyval, tagvalp)); 272e5c89e4eSSatish Balay 273bf31d2d3SBarry Smith PetscCall(PetscGetWorkingDirectory(filename, sizeof(filename) - 16)); 274c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(filename, "/petsctestshared", sizeof(filename))); 2759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 276e5c89e4eSSatish Balay 277e5c89e4eSSatish Balay /* each processor creates a file and all the later ones check */ 278e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 279e5c89e4eSSatish Balay *shared = PETSC_FALSE; 280e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 281e5c89e4eSSatish Balay if (rank == i) { 282e5c89e4eSSatish Balay fd = fopen(filename, "w"); 28328b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 284ed9cf6e9SBarry Smith err = fclose(fd); 28528b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 286e5c89e4eSSatish Balay } 2879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 288e5c89e4eSSatish Balay if (rank >= i) { 289e5c89e4eSSatish Balay fd = fopen(filename, "r"); 290a297a907SKarl Rupp if (fd) cnt = 1; 291a297a907SKarl Rupp else cnt = 0; 292e5c89e4eSSatish Balay if (fd) { 293ed9cf6e9SBarry Smith err = fclose(fd); 29428b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 295e5c89e4eSSatish Balay } 296a297a907SKarl Rupp } else cnt = 0; 297a297a907SKarl Rupp 298462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 299a297a907SKarl Rupp if (rank == i) unlink(filename); 300e5c89e4eSSatish Balay 301e5c89e4eSSatish Balay if (sum == size) { 302e5c89e4eSSatish Balay *shared = PETSC_TRUE; 303e5c89e4eSSatish Balay break; 30408401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share working directory"); 305e5c89e4eSSatish Balay } 306e5c89e4eSSatish Balay *tagvalp = (int)*shared; 307a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 3089566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "processors %s working directory\n", (*shared) ? "shared" : "do NOT share")); 3093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 310e5c89e4eSSatish Balay } 311e5c89e4eSSatish Balay 312e5c89e4eSSatish Balay /*@C 313bfbbc7b7SBarry Smith PetscFileRetrieve - Obtains a file from a URL or a compressed file 314e5c89e4eSSatish Balay and copies into local disk space as uncompressed. 315e5c89e4eSSatish Balay 316d083f849SBarry Smith Collective 317e5c89e4eSSatish Balay 318d8d19677SJose E. Roman Input Parameters: 3190c4f890aSBarry Smith + comm - processors accessing the file 3200c4f890aSBarry Smith . url - name of file, including entire URL (with or without .gz) 32121532e8aSBarry Smith - llen - length of `localname` 322e5c89e4eSSatish Balay 323d8d19677SJose E. Roman Output Parameters: 32408fb59bfSBarry Smith + localname - name of local copy of file - valid on only process zero 32508fb59bfSBarry Smith - found - if found or retrieved the file - valid on all processes 326e5c89e4eSSatish Balay 32721532e8aSBarry Smith Level: developer 3282fe279fdSBarry Smith 329811af0c4SBarry Smith Note: 33021532e8aSBarry Smith if the file already exists locally this function just returns without downloading it. 331e5c89e4eSSatish Balay 33210450e9eSJacob Faibussowitsch .seealso: `PetscDLLibraryRetrieve()` 333e5c89e4eSSatish Balay @*/ 334d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFileRetrieve(MPI_Comm comm, const char url[], char localname[], size_t llen, PetscBool *found) 335d71ae5a4SJacob Faibussowitsch { 336bbcf679cSJacob Faibussowitsch char buffer[PETSC_MAX_PATH_LEN], *par = NULL, *tlocalname = NULL, name[PETSC_MAX_PATH_LEN]; 337e5c89e4eSSatish Balay FILE *fp; 338e5c89e4eSSatish Balay PetscMPIInt rank; 339e5c89e4eSSatish Balay size_t len = 0; 34008fb59bfSBarry Smith PetscBool flg1, flg2, flg3, flg4, download, compressed = PETSC_FALSE; 341e5c89e4eSSatish Balay 342e5c89e4eSSatish Balay PetscFunctionBegin; 3439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 344dd400576SPatrick Sanan if (rank == 0) { 345e5c89e4eSSatish Balay *found = PETSC_FALSE; 346e5c89e4eSSatish Balay 3479566063dSJacob Faibussowitsch PetscCall(PetscStrstr(url, ".gz", &par)); 34808fb59bfSBarry Smith if (par) { 3499566063dSJacob Faibussowitsch PetscCall(PetscStrlen(par, &len)); 35008fb59bfSBarry Smith if (len == 3) compressed = PETSC_TRUE; 35108fb59bfSBarry Smith } 352e5c89e4eSSatish Balay 3539566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "ftp://", 6, &flg1)); 3549566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "http://", 7, &flg2)); 3559566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "file://", 7, &flg3)); 3569566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "https://", 8, &flg4)); 357a4772d12SBarry Smith download = (PetscBool)(flg1 || flg2 || flg3 || flg4); 35808fb59bfSBarry Smith 35908fb59bfSBarry Smith if (!download && !compressed) { 3609566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3619566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 362487e5849SBarry Smith if (*found) { 3639566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Found file %s\n", url)); 364487e5849SBarry Smith } else { 3659566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Did not find file %s\n", url)); 366487e5849SBarry Smith } 36708fb59bfSBarry Smith goto done; 368734f99bcSBarry Smith } 369734f99bcSBarry Smith 37005698389SBarry Smith /* look for uncompressed file in requested directory */ 37105698389SBarry Smith if (compressed) { 3729566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3739566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 37405698389SBarry Smith *par = 0; /* remove .gz extension */ 3759566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 37605698389SBarry Smith if (*found) goto done; 37705698389SBarry Smith } 37805698389SBarry Smith 37905698389SBarry Smith /* look for file in current directory */ 3809566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(url, '/', &tlocalname)); 3819566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 38208fb59bfSBarry Smith if (compressed) { 3839566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 38408fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 38508fb59bfSBarry Smith } 3869566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 38708fb59bfSBarry Smith if (*found) goto done; 388e5c89e4eSSatish Balay 38908fb59bfSBarry Smith if (download) { 39008fb59bfSBarry Smith /* local file is not already here so use curl to get it */ 3919566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 392c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(buffer, "curl --fail --silent --show-error ", sizeof(buffer))); 393c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, url, sizeof(buffer))); 394c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, " > ", sizeof(buffer))); 395c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, localname, sizeof(buffer))); 396e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN) 3979566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 3989566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 399e5c89e4eSSatish Balay #else 400e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 401e5c89e4eSSatish Balay #endif 4029566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 4036e3a5469SBarry Smith if (*found) { 4046e3a5469SBarry Smith FILE *fd; 4056e3a5469SBarry Smith char buf[1024], *str, *substring; 4066e3a5469SBarry Smith 4076e3a5469SBarry Smith /* check if the file didn't exist so it downloaded an HTML message instead */ 4086e3a5469SBarry Smith fd = fopen(localname, "r"); 40928b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscTestFile() indicates %s exists but fopen() cannot open it", localname); 4106e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4116e3a5469SBarry Smith while (str) { 4129566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "<!DOCTYPE html>", &substring)); 41328b400f6SJacob 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); 4149566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "Not Found", &substring)); 41528b400f6SJacob 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); 4166e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4176e3a5469SBarry Smith } 4186e3a5469SBarry Smith fclose(fd); 4196e3a5469SBarry Smith } 42008fb59bfSBarry Smith } else if (compressed) { 4219566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 42208fb59bfSBarry Smith if (!*found) goto done; 4239566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 42408fb59bfSBarry Smith } 42508fb59bfSBarry Smith if (compressed) { 4269566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(localname, '/', &tlocalname)); 4279566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, tlocalname, PETSC_MAX_PATH_LEN)); 4289566063dSJacob Faibussowitsch PetscCall(PetscStrstr(name, ".gz", &par)); 42908fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 43008fb59bfSBarry Smith /* uncompress file */ 431c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(buffer, "gzip -c -d ", sizeof(buffer))); 432c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, localname, sizeof(buffer))); 433c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, " > ", sizeof(buffer))); 434c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, name, sizeof(buffer))); 43508fb59bfSBarry Smith #if defined(PETSC_HAVE_POPEN) 4369566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 4379566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 43808fb59bfSBarry Smith #else 43908fb59bfSBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 44008fb59bfSBarry Smith #endif 4419566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, name, llen)); 4429566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 443e5c89e4eSSatish Balay } 444e5c89e4eSSatish Balay } 445955d42a0SBarry Smith done: 4469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(found, 1, MPIU_BOOL, 0, comm)); 4476497c311SBarry Smith PetscCallMPI(MPI_Bcast(localname, (PetscMPIInt)llen, MPI_CHAR, 0, comm)); 4483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 449e5c89e4eSSatish Balay } 450