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 */ 29d6acfc2dSPierre 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; 122*b8b5be36SMartin Diehl PetscBool flg; 123*b8b5be36SMartin Diehl PetscMPIInt iflg; 124e5c89e4eSSatish Balay FILE *fd; 125ed9cf6e9SBarry Smith int err; 126e5c89e4eSSatish Balay 127e5c89e4eSSatish Balay PetscFunctionBegin; 1289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 129e5c89e4eSSatish Balay if (size == 1) { 130e5c89e4eSSatish Balay *shared = PETSC_TRUE; 1313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 132e5c89e4eSSatish Balay } 133e5c89e4eSSatish Balay 1349566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_TMP", NULL, 0, &flg)); 135e5c89e4eSSatish Balay if (flg) { 136e5c89e4eSSatish Balay *shared = PETSC_TRUE; 1373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 138e5c89e4eSSatish Balay } 139e5c89e4eSSatish Balay 1409566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_TMP", NULL, 0, &flg)); 141e5c89e4eSSatish Balay if (flg) { 142e5c89e4eSSatish Balay *shared = PETSC_FALSE; 1433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 144e5c89e4eSSatish Balay } 145e5c89e4eSSatish Balay 1465ea2b939SDuncan Campbell if (Petsc_SharedTmp_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_SharedTmp_keyval, NULL)); 147e5c89e4eSSatish Balay 148*b8b5be36SMartin Diehl PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_SharedTmp_keyval, (void **)&tagvalp, &iflg)); 149e5c89e4eSSatish Balay if (!iflg) { 150e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN], tmpname[PETSC_MAX_PATH_LEN]; 151e5c89e4eSSatish Balay 152e5c89e4eSSatish Balay /* This communicator does not yet have a shared tmp attribute */ 1539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 1545ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_SharedTmp_keyval, tagvalp)); 155e5c89e4eSSatish Balay 156*b8b5be36SMartin Diehl PetscCall(PetscOptionsGetenv(comm, "PETSC_TMP", tmpname, 238, &flg)); 157*b8b5be36SMartin Diehl if (!flg) { 158c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(filename, "/tmp", sizeof(filename))); 159e5c89e4eSSatish Balay } else { 160c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(filename, tmpname, sizeof(filename))); 161e5c89e4eSSatish Balay } 162e5c89e4eSSatish Balay 163c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(filename, "/petsctestshared", sizeof(filename))); 1649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 165e5c89e4eSSatish Balay 166e5c89e4eSSatish Balay /* each processor creates a /tmp file and all the later ones check */ 167e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 168e5c89e4eSSatish Balay *shared = PETSC_FALSE; 169e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 170e5c89e4eSSatish Balay if (rank == i) { 171e5c89e4eSSatish Balay fd = fopen(filename, "w"); 17228b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 173ed9cf6e9SBarry Smith err = fclose(fd); 17428b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 175e5c89e4eSSatish Balay } 1769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 177e5c89e4eSSatish Balay if (rank >= i) { 178e5c89e4eSSatish Balay fd = fopen(filename, "r"); 179a297a907SKarl Rupp if (fd) cnt = 1; 180a297a907SKarl Rupp else cnt = 0; 181e5c89e4eSSatish Balay if (fd) { 182ed9cf6e9SBarry Smith err = fclose(fd); 18328b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 184e5c89e4eSSatish Balay } 185a297a907SKarl Rupp } else cnt = 0; 186a297a907SKarl Rupp 187462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 188a297a907SKarl Rupp if (rank == i) unlink(filename); 189e5c89e4eSSatish Balay 190e5c89e4eSSatish Balay if (sum == size) { 191e5c89e4eSSatish Balay *shared = PETSC_TRUE; 192e5c89e4eSSatish Balay break; 19308401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share /tmp "); 194e5c89e4eSSatish Balay } 195e5c89e4eSSatish Balay *tagvalp = (int)*shared; 196*b8b5be36SMartin Diehl PetscCall(PetscInfo(NULL, "processors %s %s\n", *shared ? "share" : "do NOT share", flg ? tmpname : "/tmp")); 197a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 1983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 199e5c89e4eSSatish Balay } 200e5c89e4eSSatish Balay 20110450e9eSJacob Faibussowitsch // "Unknown section 'Environmental Variables'" 20210450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown 203cc4c1da9SBarry Smith /*@ 204f1a722f8SMatthew G. Knepley PetscSharedWorkingDirectory - Determines if all processors in a communicator share a working directory or have different ones. 205e5c89e4eSSatish Balay 206d083f849SBarry Smith Collective 207e5c89e4eSSatish Balay 2086b867d5aSJose E. Roman Input Parameter: 209e5c89e4eSSatish Balay . comm - MPI_Communicator that may share working directory 210e5c89e4eSSatish Balay 2116b867d5aSJose E. Roman Output Parameter: 212811af0c4SBarry Smith . shared - `PETSC_TRUE` or `PETSC_FALSE` 213e5c89e4eSSatish Balay 214e5c89e4eSSatish Balay Options Database Keys: 21521532e8aSBarry Smith + -shared_working_directory - indicates the directory is known to be shared among the MPI processes 21621532e8aSBarry Smith - -not_shared_working_directory - indicates the directory is known to be not shared among the MPI processes 217e5c89e4eSSatish Balay 218e5c89e4eSSatish Balay Environmental Variables: 21921532e8aSBarry Smith + `PETSC_SHARED_WORKING_DIRECTORY` - indicates the directory is known to be shared among the MPI processes 22021532e8aSBarry Smith - `PETSC_NOT_SHARED_WORKING_DIRECTORY` - indicates the directory is known to be not shared among the MPI processes 221e5c89e4eSSatish Balay 222e5c89e4eSSatish Balay Level: developer 223e5c89e4eSSatish Balay 224e5c89e4eSSatish Balay Notes: 225f1a722f8SMatthew G. Knepley Stores the status as a MPI attribute so it does not have to be redetermined each time. 226e5c89e4eSSatish Balay 227e5c89e4eSSatish Balay Assumes that all processors in a communicator either 228bfbbc7b7SBarry Smith .vb 229bfbbc7b7SBarry Smith 1) have a common working directory or 230bfbbc7b7SBarry Smith 2) each has a separate working directory 231bfbbc7b7SBarry Smith .ve 232f1a722f8SMatthew G. Knepley eventually we can write a fancier one that determines which processors share a common working directory. 233e5c89e4eSSatish Balay 234f1a722f8SMatthew G. Knepley This will be very slow on runs with a large number of processors since it requires O(p*p) file opens. 235811af0c4SBarry Smith 236811af0c4SBarry Smith .seealso: `PetscGetTmp()`, `PetscSharedTmp()`, `PetscGetWorkingDirectory()`, `PetscGetHomeDirectory()` 237e5c89e4eSSatish Balay @*/ 238d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSharedWorkingDirectory(MPI_Comm comm, PetscBool *shared) 239d71ae5a4SJacob Faibussowitsch { 240e5c89e4eSSatish Balay PetscMPIInt size, rank, *tagvalp, sum, cnt, i; 241*b8b5be36SMartin Diehl PetscBool flg; 242*b8b5be36SMartin Diehl PetscMPIInt iflg; 243e5c89e4eSSatish Balay FILE *fd; 244ed9cf6e9SBarry Smith int err; 245e5c89e4eSSatish Balay 246e5c89e4eSSatish Balay PetscFunctionBegin; 2479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 248e5c89e4eSSatish Balay if (size == 1) { 249e5c89e4eSSatish Balay *shared = PETSC_TRUE; 2503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 251e5c89e4eSSatish Balay } 252e5c89e4eSSatish Balay 2539566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 254e5c89e4eSSatish Balay if (flg) { 255e5c89e4eSSatish Balay *shared = PETSC_TRUE; 2563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 257e5c89e4eSSatish Balay } 258e5c89e4eSSatish Balay 2599566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(comm, "PETSC_NOT_SHARED_WORKING_DIRECTORY", NULL, 0, &flg)); 260e5c89e4eSSatish Balay if (flg) { 261e5c89e4eSSatish Balay *shared = PETSC_FALSE; 2623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 263e5c89e4eSSatish Balay } 264e5c89e4eSSatish Balay 2655ea2b939SDuncan Campbell if (Petsc_SharedWD_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelTmpShared, &Petsc_SharedWD_keyval, NULL)); 266e5c89e4eSSatish Balay 267*b8b5be36SMartin Diehl PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_SharedWD_keyval, (void **)&tagvalp, &iflg)); 268e5c89e4eSSatish Balay if (!iflg) { 269e5c89e4eSSatish Balay char filename[PETSC_MAX_PATH_LEN]; 270e5c89e4eSSatish Balay 271e5c89e4eSSatish Balay /* This communicator does not yet have a shared attribute */ 2729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &tagvalp)); 2735ea2b939SDuncan Campbell PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_SharedWD_keyval, tagvalp)); 274e5c89e4eSSatish Balay 275bf31d2d3SBarry Smith PetscCall(PetscGetWorkingDirectory(filename, sizeof(filename) - 16)); 276c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(filename, "/petsctestshared", sizeof(filename))); 2779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 278e5c89e4eSSatish Balay 279e5c89e4eSSatish Balay /* each processor creates a file and all the later ones check */ 280e5c89e4eSSatish Balay /* this makes sure no subset of processors is shared */ 281e5c89e4eSSatish Balay *shared = PETSC_FALSE; 282e5c89e4eSSatish Balay for (i = 0; i < size - 1; i++) { 283e5c89e4eSSatish Balay if (rank == i) { 284e5c89e4eSSatish Balay fd = fopen(filename, "w"); 28528b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open test file %s", filename); 286ed9cf6e9SBarry Smith err = fclose(fd); 28728b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 288e5c89e4eSSatish Balay } 2899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 290e5c89e4eSSatish Balay if (rank >= i) { 291e5c89e4eSSatish Balay fd = fopen(filename, "r"); 292a297a907SKarl Rupp if (fd) cnt = 1; 293a297a907SKarl Rupp else cnt = 0; 294e5c89e4eSSatish Balay if (fd) { 295ed9cf6e9SBarry Smith err = fclose(fd); 29628b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 297e5c89e4eSSatish Balay } 298a297a907SKarl Rupp } else cnt = 0; 299a297a907SKarl Rupp 300462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&cnt, &sum, 1, MPI_INT, MPI_SUM, comm)); 301a297a907SKarl Rupp if (rank == i) unlink(filename); 302e5c89e4eSSatish Balay 303e5c89e4eSSatish Balay if (sum == size) { 304e5c89e4eSSatish Balay *shared = PETSC_TRUE; 305e5c89e4eSSatish Balay break; 30608401ef6SPierre Jolivet } else PetscCheck(sum == 1, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Subset of processes share working directory"); 307e5c89e4eSSatish Balay } 308e5c89e4eSSatish Balay *tagvalp = (int)*shared; 309a297a907SKarl Rupp } else *shared = (PetscBool)*tagvalp; 3109566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "processors %s working directory\n", (*shared) ? "shared" : "do NOT share")); 3113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 312e5c89e4eSSatish Balay } 313e5c89e4eSSatish Balay 314e5c89e4eSSatish Balay /*@C 315bfbbc7b7SBarry Smith PetscFileRetrieve - Obtains a file from a URL or a compressed file 316e5c89e4eSSatish Balay and copies into local disk space as uncompressed. 317e5c89e4eSSatish Balay 318d083f849SBarry Smith Collective 319e5c89e4eSSatish Balay 320d8d19677SJose E. Roman Input Parameters: 3210c4f890aSBarry Smith + comm - processors accessing the file 3220c4f890aSBarry Smith . url - name of file, including entire URL (with or without .gz) 32321532e8aSBarry Smith - llen - length of `localname` 324e5c89e4eSSatish Balay 325d8d19677SJose E. Roman Output Parameters: 32608fb59bfSBarry Smith + localname - name of local copy of file - valid on only process zero 32708fb59bfSBarry Smith - found - if found or retrieved the file - valid on all processes 328e5c89e4eSSatish Balay 32921532e8aSBarry Smith Level: developer 3302fe279fdSBarry Smith 331811af0c4SBarry Smith Note: 33221532e8aSBarry Smith if the file already exists locally this function just returns without downloading it. 333e5c89e4eSSatish Balay 33410450e9eSJacob Faibussowitsch .seealso: `PetscDLLibraryRetrieve()` 335e5c89e4eSSatish Balay @*/ 336d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFileRetrieve(MPI_Comm comm, const char url[], char localname[], size_t llen, PetscBool *found) 337d71ae5a4SJacob Faibussowitsch { 338bbcf679cSJacob Faibussowitsch char buffer[PETSC_MAX_PATH_LEN], *par = NULL, *tlocalname = NULL, name[PETSC_MAX_PATH_LEN]; 339e5c89e4eSSatish Balay FILE *fp; 340e5c89e4eSSatish Balay PetscMPIInt rank; 341e5c89e4eSSatish Balay size_t len = 0; 34208fb59bfSBarry Smith PetscBool flg1, flg2, flg3, flg4, download, compressed = PETSC_FALSE; 343e5c89e4eSSatish Balay 344e5c89e4eSSatish Balay PetscFunctionBegin; 3459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 346dd400576SPatrick Sanan if (rank == 0) { 347e5c89e4eSSatish Balay *found = PETSC_FALSE; 348e5c89e4eSSatish Balay 3499566063dSJacob Faibussowitsch PetscCall(PetscStrstr(url, ".gz", &par)); 35008fb59bfSBarry Smith if (par) { 3519566063dSJacob Faibussowitsch PetscCall(PetscStrlen(par, &len)); 35208fb59bfSBarry Smith if (len == 3) compressed = PETSC_TRUE; 35308fb59bfSBarry Smith } 354e5c89e4eSSatish Balay 3559566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "ftp://", 6, &flg1)); 3569566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "http://", 7, &flg2)); 3579566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "file://", 7, &flg3)); 3589566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(url, "https://", 8, &flg4)); 359a4772d12SBarry Smith download = (PetscBool)(flg1 || flg2 || flg3 || flg4); 36008fb59bfSBarry Smith 36108fb59bfSBarry Smith if (!download && !compressed) { 3629566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3639566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 364487e5849SBarry Smith if (*found) { 3659566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Found file %s\n", url)); 366487e5849SBarry Smith } else { 3679566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Did not find file %s\n", url)); 368487e5849SBarry Smith } 36908fb59bfSBarry Smith goto done; 370734f99bcSBarry Smith } 371734f99bcSBarry Smith 37205698389SBarry Smith /* look for uncompressed file in requested directory */ 37305698389SBarry Smith if (compressed) { 3749566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 3759566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 37605698389SBarry Smith *par = 0; /* remove .gz extension */ 3779566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 37805698389SBarry Smith if (*found) goto done; 37905698389SBarry Smith } 38005698389SBarry Smith 38105698389SBarry Smith /* look for file in current directory */ 3829566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(url, '/', &tlocalname)); 3839566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 38408fb59bfSBarry Smith if (compressed) { 3859566063dSJacob Faibussowitsch PetscCall(PetscStrstr(localname, ".gz", &par)); 38608fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 38708fb59bfSBarry Smith } 3889566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 38908fb59bfSBarry Smith if (*found) goto done; 390e5c89e4eSSatish Balay 39108fb59bfSBarry Smith if (download) { 39208fb59bfSBarry Smith /* local file is not already here so use curl to get it */ 3939566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, tlocalname, llen)); 394c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(buffer, "curl --fail --silent --show-error ", sizeof(buffer))); 395c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, url, sizeof(buffer))); 396c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, " > ", sizeof(buffer))); 397c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, localname, sizeof(buffer))); 398e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN) 3999566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 4009566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 401e5c89e4eSSatish Balay #else 402e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 403e5c89e4eSSatish Balay #endif 4049566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 4056e3a5469SBarry Smith if (*found) { 4066e3a5469SBarry Smith FILE *fd; 4076e3a5469SBarry Smith char buf[1024], *str, *substring; 4086e3a5469SBarry Smith 4096e3a5469SBarry Smith /* check if the file didn't exist so it downloaded an HTML message instead */ 4106e3a5469SBarry Smith fd = fopen(localname, "r"); 41128b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscTestFile() indicates %s exists but fopen() cannot open it", localname); 4126e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4136e3a5469SBarry Smith while (str) { 4149566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "<!DOCTYPE html>", &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); 4169566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buf, "Not Found", &substring)); 41728b400f6SJacob 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); 4186e3a5469SBarry Smith str = fgets(buf, sizeof(buf) - 1, fd); 4196e3a5469SBarry Smith } 4206e3a5469SBarry Smith fclose(fd); 4216e3a5469SBarry Smith } 42208fb59bfSBarry Smith } else if (compressed) { 4239566063dSJacob Faibussowitsch PetscCall(PetscTestFile(url, 'r', found)); 42408fb59bfSBarry Smith if (!*found) goto done; 4259566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, url, llen)); 42608fb59bfSBarry Smith } 42708fb59bfSBarry Smith if (compressed) { 4289566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(localname, '/', &tlocalname)); 4299566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, tlocalname, PETSC_MAX_PATH_LEN)); 4309566063dSJacob Faibussowitsch PetscCall(PetscStrstr(name, ".gz", &par)); 43108fb59bfSBarry Smith *par = 0; /* remove .gz extension */ 43208fb59bfSBarry Smith /* uncompress file */ 433c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(buffer, "gzip -c -d ", sizeof(buffer))); 434c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, localname, sizeof(buffer))); 435c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, " > ", sizeof(buffer))); 436c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(buffer, name, sizeof(buffer))); 43708fb59bfSBarry Smith #if defined(PETSC_HAVE_POPEN) 4389566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, buffer, "r", &fp)); 4399566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 44008fb59bfSBarry Smith #else 44108fb59bfSBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 44208fb59bfSBarry Smith #endif 4439566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(localname, name, llen)); 4449566063dSJacob Faibussowitsch PetscCall(PetscTestFile(localname, 'r', found)); 445e5c89e4eSSatish Balay } 446e5c89e4eSSatish Balay } 447955d42a0SBarry Smith done: 4489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(found, 1, MPIU_BOOL, 0, comm)); 4496497c311SBarry Smith PetscCallMPI(MPI_Bcast(localname, (PetscMPIInt)llen, MPI_CHAR, 0, comm)); 4503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 451e5c89e4eSSatish Balay } 452