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 2721532e8aSBarry Smith This is called by MPI, not by users, when communicator attributes are deleted 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 40*10450e9eSJacob Faibussowitsch // "Unknown section 'Environmental Variables'" 41*10450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown 42e5c89e4eSSatish Balay /*@C 4321532e8aSBarry Smith PetscGetTmp - Gets the name of the "tmp" directory, often this is `/tmp` 44e5c89e4eSSatish Balay 45d083f849SBarry Smith Collective 46e5c89e4eSSatish Balay 47e5c89e4eSSatish Balay Input Parameters: 4821532e8aSBarry Smith + comm - MPI_Communicator that may share tmp 49e5c89e4eSSatish Balay - len - length of string to hold name 50e5c89e4eSSatish Balay 51f899ff85SJose E. Roman Output Parameter: 52e5c89e4eSSatish Balay . dir - directory name 53e5c89e4eSSatish Balay 54e5c89e4eSSatish Balay Options Database Keys: 5521532e8aSBarry Smith + -shared_tmp - indicates the directory is known to be shared among the MPI processes 5621532e8aSBarry Smith . -not_shared_tmp - indicates the directory is known to be not shared among the MPI processes 5721532e8aSBarry Smith - -tmp tmpdir - name of the directory you wish to use as tmp 58e5c89e4eSSatish Balay 59e5c89e4eSSatish Balay Environmental Variables: 6021532e8aSBarry Smith + `PETSC_SHARED_TMP` - indicates the directory is known to be shared among the MPI processes 6121532e8aSBarry Smith . `PETSC_NOT_SHARED_TMP` - indicates the directory is known to be not shared among the MPI processes 6221532e8aSBarry Smith - `PETSC_TMP` - name of the directory you wish to use as tmp 63e5c89e4eSSatish Balay 64e5c89e4eSSatish Balay Level: developer 65e5c89e4eSSatish Balay 66811af0c4SBarry Smith .seealso: `PetscSharedTmp()`, `PetscSharedWorkingDirectory()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 67e5c89e4eSSatish Balay @*/ 68d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGetTmp(MPI_Comm comm, char dir[], size_t len) 69d71ae5a4SJacob Faibussowitsch { 70ace3abfcSBarry Smith PetscBool flg; 71e5c89e4eSSatish Balay 72e5c89e4eSSatish Balay PetscFunctionBegin; 739566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_TMP", dir, len, &flg)); 7448a46eb9SPierre Jolivet if (!flg) PetscCall(PetscStrncpy(dir, "/tmp", len)); 753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 76e5c89e4eSSatish Balay } 77e5c89e4eSSatish Balay 78*10450e9eSJacob Faibussowitsch // "Unknown section 'Environmental Variables'" 79*10450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown 80e5c89e4eSSatish Balay /*@C 81e5c89e4eSSatish Balay PetscSharedTmp - Determines if all processors in a communicator share a 8221532e8aSBarry Smith tmp directory or have different ones. 83e5c89e4eSSatish Balay 84d083f849SBarry Smith Collective 85e5c89e4eSSatish Balay 86811af0c4SBarry Smith Input Parameter: 8721532e8aSBarry Smith . comm - MPI_Communicator that may share tmp 88e5c89e4eSSatish Balay 89811af0c4SBarry Smith Output Parameter: 90811af0c4SBarry Smith . shared - `PETSC_TRUE` or `PETSC_FALSE` 91e5c89e4eSSatish Balay 92e5c89e4eSSatish Balay Options Database Keys: 9321532e8aSBarry Smith + -shared_tmp - indicates the directory is known to be shared among the MPI processes 9421532e8aSBarry Smith . -not_shared_tmp - indicates the directory is known to be not shared among the MPI processes 9521532e8aSBarry Smith - -tmp tmpdir - name of the directory you wish to use as tmp 96e5c89e4eSSatish Balay 97e5c89e4eSSatish Balay Environmental Variables: 9821532e8aSBarry Smith + `PETSC_SHARED_TMP` - indicates the directory is known to be shared among the MPI processes 9921532e8aSBarry Smith . `PETSC_NOT_SHARED_TMP` - indicates the directory is known to be not shared among the MPI processes 10021532e8aSBarry Smith - `PETSC_TMP` - name of the directory you wish to use as tmp 101e5c89e4eSSatish Balay 102e5c89e4eSSatish Balay Level: developer 103e5c89e4eSSatish Balay 104e5c89e4eSSatish Balay Notes: 105e5c89e4eSSatish Balay Stores the status as a MPI attribute so it does not have 106e5c89e4eSSatish Balay to be redetermined each time. 107e5c89e4eSSatish Balay 108e5c89e4eSSatish Balay Assumes that all processors in a communicator either 10921532e8aSBarry Smith 1) have a common tmp or 11021532e8aSBarry Smith 2) each has a separate tmp 111e5c89e4eSSatish Balay eventually we can write a fancier one that determines which processors 11221532e8aSBarry Smith share a common tmp. 113e5c89e4eSSatish Balay 114e5c89e4eSSatish Balay This will be very slow on runs with a large number of processors since 115e5c89e4eSSatish Balay it requires O(p*p) file opens. 116e5c89e4eSSatish Balay 117bfbbc7b7SBarry Smith If the environmental variable `PETSC_TMP` is set it will use this directory 11821532e8aSBarry Smith as the "tmp" directory. 119e5c89e4eSSatish Balay 120811af0c4SBarry Smith .seealso: `PetscGetTmp()`, `PetscSharedWorkingDirectory()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 121e5c89e4eSSatish Balay @*/ 122d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSharedTmp(MPI_Comm comm, PetscBool *shared) 123d71ae5a4SJacob Faibussowitsch { 124e5c89e4eSSatish Balay PetscMPIInt size, rank, *tagvalp, sum, cnt, i; 125ace3abfcSBarry Smith PetscBool flg, iflg; 126e5c89e4eSSatish Balay FILE *fd; 127ed9cf6e9SBarry Smith int err; 128e5c89e4eSSatish Balay 129e5c89e4eSSatish Balay PetscFunctionBegin; 1309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 131e5c89e4eSSatish Balay if (size == 1) { 132e5c89e4eSSatish Balay *shared = PETSC_TRUE; 1333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 134e5c89e4eSSatish Balay } 135e5c89e4eSSatish Balay 1369566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_TMP", NULL, 0, &flg)); 137e5c89e4eSSatish Balay if (flg) { 138e5c89e4eSSatish Balay *shared = PETSC_TRUE; 1393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 140e5c89e4eSSatish Balay } 141e5c89e4eSSatish Balay 1429566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_TMP", NULL, 0, &flg)); 143e5c89e4eSSatish Balay if (flg) { 144e5c89e4eSSatish Balay *shared = PETSC_FALSE; 1453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146e5c89e4eSSatish Balay } 147e5c89e4eSSatish Balay 1485ea2b939SDuncan Campbell if (Petsc_SharedTmp_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_SharedTmp_keyval, NULL)); 149e5c89e4eSSatish Balay 1505ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_SharedTmp_keyval, (void **)&tagvalp, (int *)&iflg)); 151e5c89e4eSSatish Balay if (!iflg) { 152e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN], tmpname[PETSC_MAX_PATH_LEN]; 153e5c89e4eSSatish Balay 154e5c89e4eSSatish Balay /* This communicator does not yet have a shared tmp attribute */ 1559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 1565ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_SharedTmp_keyval, tagvalp)); 157e5c89e4eSSatish Balay 1589566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_TMP", tmpname, 238, &iflg)); 159e5c89e4eSSatish Balay if (!iflg) { 160c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(filename, "/tmp", sizeof(filename))); 161e5c89e4eSSatish Balay } else { 162c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(filename, tmpname, sizeof(filename))); 163e5c89e4eSSatish Balay } 164e5c89e4eSSatish Balay 165c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(filename, "/petsctestshared", sizeof(filename))); 1669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 167e5c89e4eSSatish Balay 168e5c89e4eSSatish Balay /* each processor creates a /tmp file and all the later ones check */ 169e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 170e5c89e4eSSatish Balay *shared = PETSC_FALSE; 171e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 172e5c89e4eSSatish Balay if (rank == i) { 173e5c89e4eSSatish Balay fd = fopen(filename, "w"); 17428b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 175ed9cf6e9SBarry Smith err = fclose(fd); 17628b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 177e5c89e4eSSatish Balay } 1789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 179e5c89e4eSSatish Balay if (rank >= i) { 180e5c89e4eSSatish Balay fd = fopen(filename, "r"); 181a297a907SKarl Rupp if (fd) cnt = 1; 182a297a907SKarl Rupp else cnt = 0; 183e5c89e4eSSatish Balay if (fd) { 184ed9cf6e9SBarry Smith err = fclose(fd); 18528b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 186e5c89e4eSSatish Balay } 187a297a907SKarl Rupp } else cnt = 0; 188a297a907SKarl Rupp 1891c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 190a297a907SKarl Rupp if (rank == i) unlink(filename); 191e5c89e4eSSatish Balay 192e5c89e4eSSatish Balay if (sum == size) { 193e5c89e4eSSatish Balay *shared = PETSC_TRUE; 194e5c89e4eSSatish Balay break; 19508401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share /tmp "); 196e5c89e4eSSatish Balay } 197e5c89e4eSSatish Balay *tagvalp = (int)*shared; 1989566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "processors %s %s\n", (*shared) ? "share" : "do NOT share", (iflg ? tmpname : "/tmp"))); 199a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 2003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 201e5c89e4eSSatish Balay } 202e5c89e4eSSatish Balay 203*10450e9eSJacob Faibussowitsch // "Unknown section 'Environmental Variables'" 204*10450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown 205e5c89e4eSSatish Balay /*@C 206f1a722f8SMatthew G. Knepley PetscSharedWorkingDirectory - Determines if all processors in a communicator share a working directory or have different ones. 207e5c89e4eSSatish Balay 208d083f849SBarry Smith Collective 209e5c89e4eSSatish Balay 2106b867d5aSJose E. Roman Input Parameter: 211e5c89e4eSSatish Balay . comm - MPI_Communicator that may share working directory 212e5c89e4eSSatish Balay 2136b867d5aSJose E. Roman Output Parameter: 214811af0c4SBarry Smith . shared - `PETSC_TRUE` or `PETSC_FALSE` 215e5c89e4eSSatish Balay 216e5c89e4eSSatish Balay Options Database Keys: 21721532e8aSBarry Smith + -shared_working_directory - indicates the directory is known to be shared among the MPI processes 21821532e8aSBarry Smith - -not_shared_working_directory - indicates the directory is known to be not shared among the MPI processes 219e5c89e4eSSatish Balay 220e5c89e4eSSatish Balay Environmental Variables: 22121532e8aSBarry Smith + `PETSC_SHARED_WORKING_DIRECTORY` - indicates the directory is known to be shared among the MPI processes 22221532e8aSBarry Smith - `PETSC_NOT_SHARED_WORKING_DIRECTORY` - indicates the directory is known to be not shared among the MPI processes 223e5c89e4eSSatish Balay 224e5c89e4eSSatish Balay Level: developer 225e5c89e4eSSatish Balay 226e5c89e4eSSatish Balay Notes: 227f1a722f8SMatthew G. Knepley Stores the status as a MPI attribute so it does not have to be redetermined each time. 228e5c89e4eSSatish Balay 229e5c89e4eSSatish Balay Assumes that all processors in a communicator either 230bfbbc7b7SBarry Smith .vb 231bfbbc7b7SBarry Smith 1) have a common working directory or 232bfbbc7b7SBarry Smith 2) each has a separate working directory 233bfbbc7b7SBarry Smith .ve 234f1a722f8SMatthew G. Knepley eventually we can write a fancier one that determines which processors share a common working directory. 235e5c89e4eSSatish Balay 236f1a722f8SMatthew G. Knepley This will be very slow on runs with a large number of processors since it requires O(p*p) file opens. 237811af0c4SBarry Smith 238811af0c4SBarry Smith .seealso: `PetscGetTmp()`, `PetscSharedTmp()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 239e5c89e4eSSatish Balay @*/ 240d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSharedWorkingDirectory(MPI_Comm comm, PetscBool *shared) 241d71ae5a4SJacob Faibussowitsch { 242e5c89e4eSSatish Balay PetscMPIInt size, rank, *tagvalp, sum, cnt, i; 243ace3abfcSBarry Smith PetscBool flg, iflg; 244e5c89e4eSSatish Balay FILE *fd; 245ed9cf6e9SBarry Smith int err; 246e5c89e4eSSatish Balay 247e5c89e4eSSatish Balay PetscFunctionBegin; 2489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 249e5c89e4eSSatish Balay if (size == 1) { 250e5c89e4eSSatish Balay *shared = PETSC_TRUE; 2513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 252e5c89e4eSSatish Balay } 253e5c89e4eSSatish Balay 2549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 255e5c89e4eSSatish Balay if (flg) { 256e5c89e4eSSatish Balay *shared = PETSC_TRUE; 2573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 258e5c89e4eSSatish Balay } 259e5c89e4eSSatish Balay 2609566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 261e5c89e4eSSatish Balay if (flg) { 262e5c89e4eSSatish Balay *shared = PETSC_FALSE; 2633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 264e5c89e4eSSatish Balay } 265e5c89e4eSSatish Balay 2665ea2b939SDuncan Campbell if (Petsc_SharedWD_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_SharedWD_keyval, NULL)); 267e5c89e4eSSatish Balay 2685ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_SharedWD_keyval, (void **)&tagvalp, (int *)&iflg)); 269e5c89e4eSSatish Balay if (!iflg) { 270e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN]; 271e5c89e4eSSatish Balay 272e5c89e4eSSatish Balay /* This communicator does not yet have a shared attribute */ 2739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 2745ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_SharedWD_keyval, tagvalp)); 275e5c89e4eSSatish Balay 276bf31d2d3SBarry Smith PetscCall(PetscGetWorkingDirectory(filename, sizeof(filename) - 16)); 277c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(filename, "/petsctestshared", sizeof(filename))); 2789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 279e5c89e4eSSatish Balay 280e5c89e4eSSatish Balay /* each processor creates a file and all the later ones check */ 281e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 282e5c89e4eSSatish Balay *shared = PETSC_FALSE; 283e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 284e5c89e4eSSatish Balay if (rank == i) { 285e5c89e4eSSatish Balay fd = fopen(filename, "w"); 28628b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 287ed9cf6e9SBarry Smith err = fclose(fd); 28828b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 289e5c89e4eSSatish Balay } 2909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 291e5c89e4eSSatish Balay if (rank >= i) { 292e5c89e4eSSatish Balay fd = fopen(filename, "r"); 293a297a907SKarl Rupp if (fd) cnt = 1; 294a297a907SKarl Rupp else cnt = 0; 295e5c89e4eSSatish Balay if (fd) { 296ed9cf6e9SBarry Smith err = fclose(fd); 29728b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 298e5c89e4eSSatish Balay } 299a297a907SKarl Rupp } else cnt = 0; 300a297a907SKarl Rupp 3011c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 302a297a907SKarl Rupp if (rank == i) unlink(filename); 303e5c89e4eSSatish Balay 304e5c89e4eSSatish Balay if (sum == size) { 305e5c89e4eSSatish Balay *shared = PETSC_TRUE; 306e5c89e4eSSatish Balay break; 30708401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share working directory"); 308e5c89e4eSSatish Balay } 309e5c89e4eSSatish Balay *tagvalp = (int)*shared; 310a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 3119566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "processors %s working directory\n", (*shared) ? "shared" : "do NOT share")); 3123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 313e5c89e4eSSatish Balay } 314e5c89e4eSSatish Balay 315e5c89e4eSSatish Balay /*@C 316bfbbc7b7SBarry Smith PetscFileRetrieve - Obtains a file from a URL or a compressed file 317e5c89e4eSSatish Balay and copies into local disk space as uncompressed. 318e5c89e4eSSatish Balay 319d083f849SBarry Smith Collective 320e5c89e4eSSatish Balay 321d8d19677SJose E. Roman Input Parameters: 3220c4f890aSBarry Smith + comm - processors accessing the file 3230c4f890aSBarry Smith . url - name of file, including entire URL (with or without .gz) 32421532e8aSBarry Smith - llen - length of `localname` 325e5c89e4eSSatish Balay 326d8d19677SJose E. Roman Output Parameters: 32708fb59bfSBarry Smith + localname - name of local copy of file - valid on only process zero 32808fb59bfSBarry Smith - found - if found or retrieved the file - valid on all processes 329e5c89e4eSSatish Balay 33021532e8aSBarry Smith Level: developer 3312fe279fdSBarry Smith 332811af0c4SBarry Smith Note: 33321532e8aSBarry Smith if the file already exists locally this function just returns without downloading it. 334e5c89e4eSSatish Balay 335*10450e9eSJacob Faibussowitsch .seealso: `PetscDLLibraryRetrieve()` 336e5c89e4eSSatish Balay @*/ 337d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFileRetrieve(MPI_Comm comm, const char url[], char localname[], size_t llen, PetscBool *found) 338d71ae5a4SJacob Faibussowitsch { 339bbcf679cSJacob Faibussowitsch char buffer[PETSC_MAX_PATH_LEN], *par = NULL, *tlocalname = NULL, name[PETSC_MAX_PATH_LEN]; 340e5c89e4eSSatish Balay FILE *fp; 341e5c89e4eSSatish Balay PetscMPIInt rank; 342e5c89e4eSSatish Balay size_t len = 0; 34308fb59bfSBarry Smith PetscBool flg1, flg2, flg3, flg4, download, compressed = PETSC_FALSE; 344e5c89e4eSSatish Balay 345e5c89e4eSSatish Balay PetscFunctionBegin; 3469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 347dd400576SPatrick Sanan if (rank == 0) { 348e5c89e4eSSatish Balay *found = PETSC_FALSE; 349e5c89e4eSSatish Balay 3509566063dSJacob Faibussowitsch PetscCall(PetscStrstr(url, ".gz", &par)); 35108fb59bfSBarry Smith if (par) { 3529566063dSJacob Faibussowitsch PetscCall(PetscStrlen(par, &len)); 35308fb59bfSBarry Smith if (len == 3) compressed = PETSC_TRUE; 35408fb59bfSBarry Smith } 355e5c89e4eSSatish Balay 3569566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "ftp://", 6, &flg1)); 3579566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "http://", 7, &flg2)); 3589566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "file://", 7, &flg3)); 3599566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "https://", 8, &flg4)); 360a4772d12SBarry Smith download = (PetscBool)(flg1 || flg2 || flg3 || flg4); 36108fb59bfSBarry Smith 36208fb59bfSBarry Smith if (!download && !compressed) { 3639566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3649566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 365487e5849SBarry Smith if (*found) { 3669566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Found file %s\n", url)); 367487e5849SBarry Smith } else { 3689566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Did not find file %s\n", url)); 369487e5849SBarry Smith } 37008fb59bfSBarry Smith goto done; 371734f99bcSBarry Smith } 372734f99bcSBarry Smith 37305698389SBarry Smith /* look for uncompressed file in requested directory */ 37405698389SBarry Smith if (compressed) { 3759566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3769566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 37705698389SBarry Smith *par = 0; /* remove .gz extension */ 3789566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 37905698389SBarry Smith if (*found) goto done; 38005698389SBarry Smith } 38105698389SBarry Smith 38205698389SBarry Smith /* look for file in current directory */ 3839566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(url, '/', &tlocalname)); 3849566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 38508fb59bfSBarry Smith if (compressed) { 3869566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 38708fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 38808fb59bfSBarry Smith } 3899566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 39008fb59bfSBarry Smith if (*found) goto done; 391e5c89e4eSSatish Balay 39208fb59bfSBarry Smith if (download) { 39308fb59bfSBarry Smith /* local file is not already here so use curl to get it */ 3949566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 395c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(buffer, "curl --fail --silent --show-error ", sizeof(buffer))); 396c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, url, sizeof(buffer))); 397c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, " > ", sizeof(buffer))); 398c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, localname, sizeof(buffer))); 399e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN) 4009566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 4019566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 402e5c89e4eSSatish Balay #else 403e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 404e5c89e4eSSatish Balay #endif 4059566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 4066e3a5469SBarry Smith if (*found) { 4076e3a5469SBarry Smith FILE *fd; 4086e3a5469SBarry Smith char buf[1024], *str, *substring; 4096e3a5469SBarry Smith 4106e3a5469SBarry Smith /* check if the file didn't exist so it downloaded an HTML message instead */ 4116e3a5469SBarry Smith fd = fopen(localname, "r"); 41228b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscTestFile() indicates %s exists but fopen() cannot open it", localname); 4136e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4146e3a5469SBarry Smith while (str) { 4159566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "<!DOCTYPE html>", &substring)); 41628b400f6SJacob 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); 4179566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "Not Found", &substring)); 41828b400f6SJacob 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); 4196e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4206e3a5469SBarry Smith } 4216e3a5469SBarry Smith fclose(fd); 4226e3a5469SBarry Smith } 42308fb59bfSBarry Smith } else if (compressed) { 4249566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 42508fb59bfSBarry Smith if (!*found) goto done; 4269566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 42708fb59bfSBarry Smith } 42808fb59bfSBarry Smith if (compressed) { 4299566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(localname, '/', &tlocalname)); 4309566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, tlocalname, PETSC_MAX_PATH_LEN)); 4319566063dSJacob Faibussowitsch PetscCall(PetscStrstr(name, ".gz", &par)); 43208fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 43308fb59bfSBarry Smith /* uncompress file */ 434c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(buffer, "gzip -c -d ", sizeof(buffer))); 435c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, localname, sizeof(buffer))); 436c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, " > ", sizeof(buffer))); 437c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, name, sizeof(buffer))); 43808fb59bfSBarry Smith #if defined(PETSC_HAVE_POPEN) 4399566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 4409566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 44108fb59bfSBarry Smith #else 44208fb59bfSBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 44308fb59bfSBarry Smith #endif 4449566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, name, llen)); 4459566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 446e5c89e4eSSatish Balay } 447e5c89e4eSSatish Balay } 448955d42a0SBarry Smith done: 4499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(found, 1, MPIU_BOOL, 0, comm)); 4509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(localname, llen, MPI_CHAR, 0, comm)); 4513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 452e5c89e4eSSatish Balay } 453