xref: /petsc/src/sys/fileio/fretrieve.c (revision 08401ef684002a709c6d3db98a0c9f54a8bcf1ec)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay       Code for opening and closing files.
4e5c89e4eSSatish Balay */
5c6db04a5SJed Brown #include <petscsys.h>
6e5c89e4eSSatish Balay #if defined(PETSC_HAVE_PWD_H)
7e5c89e4eSSatish Balay #include <pwd.h>
8e5c89e4eSSatish Balay #endif
9e5c89e4eSSatish Balay #include <ctype.h>
10e5c89e4eSSatish Balay #include <sys/stat.h>
11e5c89e4eSSatish Balay #if defined(PETSC_HAVE_UNISTD_H)
12e5c89e4eSSatish Balay #include <unistd.h>
13e5c89e4eSSatish Balay #endif
14e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SYS_UTSNAME_H)
15e5c89e4eSSatish Balay #include <sys/utsname.h>
16e5c89e4eSSatish Balay #endif
17e5c89e4eSSatish Balay #include <fcntl.h>
18e5c89e4eSSatish Balay #include <time.h>
19e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
20e5c89e4eSSatish Balay #include <sys/systeminfo.h>
21e5c89e4eSSatish Balay #endif
22e5c89e4eSSatish Balay 
23480cf27aSJed Brown /*
24480cf27aSJed Brown    Private routine to delete tmp/shared storage
25480cf27aSJed Brown 
26480cf27aSJed Brown    This is called by MPI, not by users.
27480cf27aSJed Brown 
2812801b39SBarry Smith    Note: this is declared extern "C" because it is passed to MPI_Comm_create_keyval()
29480cf27aSJed Brown 
30480cf27aSJed Brown */
318cc058d9SJed Brown PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelTmpShared(MPI_Comm comm,PetscMPIInt keyval,void *count_val,void *extra_state)
32480cf27aSJed Brown {
33480cf27aSJed Brown   PetscFunctionBegin;
349566063dSJacob Faibussowitsch   PetscCallMPI(PetscInfo(NULL,"Deleting tmp/shared data in an MPI_Comm %ld\n",(long)comm));
359566063dSJacob Faibussowitsch   PetscCallMPI(PetscFree(count_val));
36480cf27aSJed Brown   PetscFunctionReturn(MPI_SUCCESS);
37480cf27aSJed Brown }
38e5c89e4eSSatish Balay 
39e5c89e4eSSatish Balay /*@C
40e5c89e4eSSatish Balay    PetscGetTmp - Gets the name of the tmp directory
41e5c89e4eSSatish Balay 
42d083f849SBarry Smith    Collective
43e5c89e4eSSatish Balay 
44e5c89e4eSSatish Balay    Input Parameters:
45e5c89e4eSSatish Balay +  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:
5210699b91SBarry Smith +    -shared_tmp  - indicates the directory is shared among the MPI ranks
5310699b91SBarry Smith .    -not_shared_tmp - indicates the directory is not shared among the MPI ranks
5410699b91SBarry Smith -    -tmp tmpdir - name of the directory you wish to use as /tmp
55e5c89e4eSSatish Balay 
56e5c89e4eSSatish Balay    Environmental Variables:
5710699b91SBarry Smith +     PETSC_SHARED_TMP - indicates the directory is shared among the MPI ranks
5810699b91SBarry Smith .     PETSC_NOT_SHARED_TMP - indicates the directory is not shared among the MPI ranks
5910699b91SBarry Smith -     PETSC_TMP - name of the directory you wish to use as /tmp
60e5c89e4eSSatish Balay 
61e5c89e4eSSatish Balay    Level: developer
62e5c89e4eSSatish Balay 
63e5c89e4eSSatish Balay @*/
647087cfbeSBarry Smith PetscErrorCode  PetscGetTmp(MPI_Comm comm,char dir[],size_t len)
65e5c89e4eSSatish Balay {
66ace3abfcSBarry Smith   PetscBool      flg;
67e5c89e4eSSatish Balay 
68e5c89e4eSSatish Balay   PetscFunctionBegin;
699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetenv(comm,"PETSC_TMP",dir,len,&flg));
70e5c89e4eSSatish Balay   if (!flg) {
719566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(dir,"/tmp",len));
72e5c89e4eSSatish Balay   }
73e5c89e4eSSatish Balay   PetscFunctionReturn(0);
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 
82e5c89e4eSSatish Balay    Input Parameters:
83e5c89e4eSSatish Balay .  comm - MPI_Communicator that may share /tmp
84e5c89e4eSSatish Balay 
85e5c89e4eSSatish Balay    Output Parameters:
86e5c89e4eSSatish Balay .  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:
9410699b91SBarry Smith +     PETSC_SHARED_TMP  - indicates the directory is shared among the MPI ranks
9510699b91SBarry Smith .     PETSC_NOT_SHARED_TMP - indicates the directory is not shared among the MPI ranks
9610699b91SBarry 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 
116e5c89e4eSSatish Balay @*/
1177087cfbeSBarry Smith PetscErrorCode  PetscSharedTmp(MPI_Comm comm,PetscBool  *shared)
118e5c89e4eSSatish Balay {
119e5c89e4eSSatish Balay   PetscMPIInt        size,rank,*tagvalp,sum,cnt,i;
120ace3abfcSBarry Smith   PetscBool          flg,iflg;
121e5c89e4eSSatish Balay   FILE               *fd;
122e5c89e4eSSatish Balay   static PetscMPIInt Petsc_Tmp_keyval = MPI_KEYVAL_INVALID;
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;
129e5c89e4eSSatish Balay     PetscFunctionReturn(0);
130e5c89e4eSSatish Balay   }
131e5c89e4eSSatish Balay 
1329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetenv(comm,"PETSC_SHARED_TMP",NULL,0,&flg));
133e5c89e4eSSatish Balay   if (flg) {
134e5c89e4eSSatish Balay     *shared = PETSC_TRUE;
135e5c89e4eSSatish Balay     PetscFunctionReturn(0);
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;
141e5c89e4eSSatish Balay     PetscFunctionReturn(0);
142e5c89e4eSSatish Balay   }
143e5c89e4eSSatish Balay 
144e5c89e4eSSatish Balay   if (Petsc_Tmp_keyval == MPI_KEYVAL_INVALID) {
1459566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,Petsc_DelTmpShared,&Petsc_Tmp_keyval,NULL));
146e5c89e4eSSatish Balay   }
147e5c89e4eSSatish Balay 
1489566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_get_attr(comm,Petsc_Tmp_keyval,(void**)&tagvalp,(int*)&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));
1549566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_set_attr(comm,Petsc_Tmp_keyval,tagvalp));
155e5c89e4eSSatish Balay 
1569566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetenv(comm,"PETSC_TMP",tmpname,238,&iflg));
157e5c89e4eSSatish Balay     if (!iflg) {
1589566063dSJacob Faibussowitsch       PetscCall(PetscStrcpy(filename,"/tmp"));
159e5c89e4eSSatish Balay     } else {
1609566063dSJacob Faibussowitsch       PetscCall(PetscStrcpy(filename,tmpname));
161e5c89e4eSSatish Balay     }
162e5c89e4eSSatish Balay 
1639566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(filename,"/petsctestshared"));
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 
1871c2dc1cbSBarry Smith       PetscCall(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;
193*08401ef6SPierre Jolivet       } else PetscCheck(sum == 1,PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Subset of processes share /tmp ");
194e5c89e4eSSatish Balay     }
195e5c89e4eSSatish Balay     *tagvalp = (int)*shared;
1969566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL,"processors %s %s\n",(*shared) ? "share":"do NOT share",(iflg ? tmpname:"/tmp")));
197a297a907SKarl Rupp   } else *shared = (PetscBool) *tagvalp;
198e5c89e4eSSatish Balay   PetscFunctionReturn(0);
199e5c89e4eSSatish Balay }
200e5c89e4eSSatish Balay 
201e5c89e4eSSatish Balay /*@C
202f1a722f8SMatthew G. Knepley   PetscSharedWorkingDirectory - Determines if all processors in a communicator share a working directory or have different ones.
203e5c89e4eSSatish Balay 
204d083f849SBarry Smith   Collective
205e5c89e4eSSatish Balay 
2066b867d5aSJose E. Roman   Input Parameter:
207e5c89e4eSSatish Balay . comm - MPI_Communicator that may share working directory
208e5c89e4eSSatish Balay 
2096b867d5aSJose E. Roman   Output Parameter:
210e5c89e4eSSatish Balay . shared - PETSC_TRUE or PETSC_FALSE
211e5c89e4eSSatish Balay 
212e5c89e4eSSatish Balay   Options Database Keys:
21310699b91SBarry Smith + -shared_working_directory - indicates the directory is shared among the MPI ranks
21410699b91SBarry Smith - -not_shared_working_directory - indicates the directory is shared among the MPI ranks
215e5c89e4eSSatish Balay 
216e5c89e4eSSatish Balay   Environmental Variables:
21710699b91SBarry Smith + PETSC_SHARED_WORKING_DIRECTORY - indicates the directory is shared among the MPI ranks
2183222ab0cSSatish Balay - PETSC_NOT_SHARED_WORKING_DIRECTORY - indicates the directory is shared among the MPI ranks
219e5c89e4eSSatish Balay 
220e5c89e4eSSatish Balay   Level: developer
221e5c89e4eSSatish Balay 
222e5c89e4eSSatish Balay   Notes:
223f1a722f8SMatthew G. Knepley   Stores the status as a MPI attribute so it does not have to be redetermined each time.
224e5c89e4eSSatish Balay 
225e5c89e4eSSatish Balay   Assumes that all processors in a communicator either
226f1a722f8SMatthew G. Knepley $   1) have a common working directory or
227f1a722f8SMatthew G. Knepley $   2) each has a separate working directory
228f1a722f8SMatthew G. Knepley   eventually we can write a fancier one that determines which processors share a common working directory.
229e5c89e4eSSatish Balay 
230f1a722f8SMatthew G. Knepley   This will be very slow on runs with a large number of processors since it requires O(p*p) file opens.
231e5c89e4eSSatish Balay @*/
2327087cfbeSBarry Smith PetscErrorCode PetscSharedWorkingDirectory(MPI_Comm comm, PetscBool *shared)
233e5c89e4eSSatish Balay {
234e5c89e4eSSatish Balay   PetscMPIInt        size,rank,*tagvalp,sum,cnt,i;
235ace3abfcSBarry Smith   PetscBool          flg,iflg;
236e5c89e4eSSatish Balay   FILE               *fd;
237e5c89e4eSSatish Balay   static PetscMPIInt Petsc_WD_keyval = MPI_KEYVAL_INVALID;
238ed9cf6e9SBarry Smith   int                err;
239e5c89e4eSSatish Balay 
240e5c89e4eSSatish Balay   PetscFunctionBegin;
2419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&size));
242e5c89e4eSSatish Balay   if (size == 1) {
243e5c89e4eSSatish Balay     *shared = PETSC_TRUE;
244e5c89e4eSSatish Balay     PetscFunctionReturn(0);
245e5c89e4eSSatish Balay   }
246e5c89e4eSSatish Balay 
2479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetenv(comm,"PETSC_SHARED_WORKING_DIRECTORY",NULL,0,&flg));
248e5c89e4eSSatish Balay   if (flg) {
249e5c89e4eSSatish Balay     *shared = PETSC_TRUE;
250e5c89e4eSSatish Balay     PetscFunctionReturn(0);
251e5c89e4eSSatish Balay   }
252e5c89e4eSSatish Balay 
2539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetenv(comm,"PETSC_NOT_SHARED_WORKING_DIRECTORY",NULL,0,&flg));
254e5c89e4eSSatish Balay   if (flg) {
255e5c89e4eSSatish Balay     *shared = PETSC_FALSE;
256e5c89e4eSSatish Balay     PetscFunctionReturn(0);
257e5c89e4eSSatish Balay   }
258e5c89e4eSSatish Balay 
259e5c89e4eSSatish Balay   if (Petsc_WD_keyval == MPI_KEYVAL_INVALID) {
2609566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,Petsc_DelTmpShared,&Petsc_WD_keyval,NULL));
261e5c89e4eSSatish Balay   }
262e5c89e4eSSatish Balay 
2639566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_get_attr(comm,Petsc_WD_keyval,(void**)&tagvalp,(int*)&iflg));
264e5c89e4eSSatish Balay   if (!iflg) {
265e5c89e4eSSatish Balay     char filename[PETSC_MAX_PATH_LEN];
266e5c89e4eSSatish Balay 
267e5c89e4eSSatish Balay     /* This communicator does not yet have a shared  attribute */
2689566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1,&tagvalp));
2699566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_set_attr(comm,Petsc_WD_keyval,tagvalp));
270e5c89e4eSSatish Balay 
2719566063dSJacob Faibussowitsch     PetscCall(PetscGetWorkingDirectory(filename,240));
2729566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(filename,"/petsctestshared"));
2739566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm,&rank));
274e5c89e4eSSatish Balay 
275e5c89e4eSSatish Balay     /* each processor creates a  file and all the later ones check */
276e5c89e4eSSatish Balay     /* this makes sure no subset of processors is shared */
277e5c89e4eSSatish Balay     *shared = PETSC_FALSE;
278e5c89e4eSSatish Balay     for (i=0; i<size-1; i++) {
279e5c89e4eSSatish Balay       if (rank == i) {
280e5c89e4eSSatish Balay         fd = fopen(filename,"w");
28128b400f6SJacob Faibussowitsch         PetscCheck(fd,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open test file %s",filename);
282ed9cf6e9SBarry Smith         err = fclose(fd);
28328b400f6SJacob Faibussowitsch         PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
284e5c89e4eSSatish Balay       }
2859566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Barrier(comm));
286e5c89e4eSSatish Balay       if (rank >= i) {
287e5c89e4eSSatish Balay         fd = fopen(filename,"r");
288a297a907SKarl Rupp         if (fd) cnt = 1;
289a297a907SKarl Rupp         else cnt = 0;
290e5c89e4eSSatish Balay         if (fd) {
291ed9cf6e9SBarry Smith           err = fclose(fd);
29228b400f6SJacob Faibussowitsch           PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
293e5c89e4eSSatish Balay         }
294a297a907SKarl Rupp       } else cnt = 0;
295a297a907SKarl Rupp 
2961c2dc1cbSBarry Smith       PetscCall(MPIU_Allreduce(&cnt,&sum,1,MPI_INT,MPI_SUM,comm));
297a297a907SKarl Rupp       if (rank == i) unlink(filename);
298e5c89e4eSSatish Balay 
299e5c89e4eSSatish Balay       if (sum == size) {
300e5c89e4eSSatish Balay         *shared = PETSC_TRUE;
301e5c89e4eSSatish Balay         break;
302*08401ef6SPierre Jolivet       } else PetscCheck(sum == 1,PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Subset of processes share working directory");
303e5c89e4eSSatish Balay     }
304e5c89e4eSSatish Balay     *tagvalp = (int)*shared;
305a297a907SKarl Rupp   } else *shared = (PetscBool) *tagvalp;
3069566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL,"processors %s working directory\n",(*shared) ? "shared" : "do NOT share"));
307e5c89e4eSSatish Balay   PetscFunctionReturn(0);
308e5c89e4eSSatish Balay }
309e5c89e4eSSatish Balay 
310e5c89e4eSSatish Balay /*@C
3110c4f890aSBarry Smith     PetscFileRetrieve - Obtains a file from a URL or compressed
312e5c89e4eSSatish Balay         and copies into local disk space as uncompressed.
313e5c89e4eSSatish Balay 
314d083f849SBarry Smith     Collective
315e5c89e4eSSatish Balay 
316d8d19677SJose E. Roman     Input Parameters:
3170c4f890aSBarry Smith +   comm     - processors accessing the file
3180c4f890aSBarry Smith .   url      - name of file, including entire URL (with or without .gz)
3190c4f890aSBarry Smith -   llen     - length of localname
320e5c89e4eSSatish Balay 
321d8d19677SJose E. Roman     Output Parameters:
32208fb59bfSBarry Smith +   localname - name of local copy of file - valid on only process zero
32308fb59bfSBarry Smith -   found - if found or retrieved the file - valid on all processes
324e5c89e4eSSatish Balay 
32595452b02SPatrick Sanan     Notes:
32695452b02SPatrick Sanan     if the file already exists local this function just returns without downloading it.
327e5c89e4eSSatish Balay 
3280c4f890aSBarry Smith     Level: intermediate
329e5c89e4eSSatish Balay @*/
3300c4f890aSBarry Smith PetscErrorCode  PetscFileRetrieve(MPI_Comm comm,const char url[],char localname[],size_t llen,PetscBool  *found)
331e5c89e4eSSatish Balay {
33208fb59bfSBarry Smith   char           buffer[PETSC_MAX_PATH_LEN],*par,*tlocalname,name[PETSC_MAX_PATH_LEN];
333e5c89e4eSSatish Balay   FILE           *fp;
334e5c89e4eSSatish Balay   PetscMPIInt    rank;
335e5c89e4eSSatish Balay   size_t         len = 0;
33608fb59bfSBarry Smith   PetscBool      flg1,flg2,flg3,flg4,download,compressed = PETSC_FALSE;
337e5c89e4eSSatish Balay 
338e5c89e4eSSatish Balay   PetscFunctionBegin;
3399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
340dd400576SPatrick Sanan   if (rank == 0) {
341e5c89e4eSSatish Balay     *found = PETSC_FALSE;
342e5c89e4eSSatish Balay 
3439566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(url,".gz",&par));
34408fb59bfSBarry Smith     if (par) {
3459566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(par,&len));
34608fb59bfSBarry Smith       if (len == 3) compressed = PETSC_TRUE;
34708fb59bfSBarry Smith     }
348e5c89e4eSSatish Balay 
3499566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(url,"ftp://",6,&flg1));
3509566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(url,"http://",7,&flg2));
3519566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(url,"file://",7,&flg3));
3529566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(url,"https://",8,&flg4));
353a4772d12SBarry Smith     download = (PetscBool) (flg1 || flg2 || flg3 || flg4);
35408fb59bfSBarry Smith 
35508fb59bfSBarry Smith     if (!download && !compressed) {
3569566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(localname,url,llen));
3579566063dSJacob Faibussowitsch       PetscCall(PetscTestFile(url,'r',found));
358487e5849SBarry Smith       if (*found) {
3599566063dSJacob Faibussowitsch         PetscCall(PetscInfo(NULL,"Found file %s\n",url));
360487e5849SBarry Smith       } else {
3619566063dSJacob Faibussowitsch         PetscCall(PetscInfo(NULL,"Did not find file %s\n",url));
362487e5849SBarry Smith       }
36308fb59bfSBarry Smith       goto done;
364734f99bcSBarry Smith     }
365734f99bcSBarry Smith 
36605698389SBarry Smith     /* look for uncompressed file in requested directory */
36705698389SBarry Smith     if (compressed) {
3689566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(localname,url,llen));
3699566063dSJacob Faibussowitsch       PetscCall(PetscStrstr(localname,".gz",&par));
37005698389SBarry Smith       *par = 0; /* remove .gz extension */
3719566063dSJacob Faibussowitsch       PetscCall(PetscTestFile(localname,'r',found));
37205698389SBarry Smith       if (*found) goto done;
37305698389SBarry Smith     }
37405698389SBarry Smith 
37505698389SBarry Smith     /* look for file in current directory */
3769566063dSJacob Faibussowitsch     PetscCall(PetscStrrchr(url,'/',&tlocalname));
3779566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(localname,tlocalname,llen));
37808fb59bfSBarry Smith     if (compressed) {
3799566063dSJacob Faibussowitsch       PetscCall(PetscStrstr(localname,".gz",&par));
38008fb59bfSBarry Smith       *par = 0; /* remove .gz extension */
38108fb59bfSBarry Smith     }
3829566063dSJacob Faibussowitsch     PetscCall(PetscTestFile(localname,'r',found));
38308fb59bfSBarry Smith     if (*found) goto done;
384e5c89e4eSSatish Balay 
38508fb59bfSBarry Smith     if (download) {
38608fb59bfSBarry Smith       /* local file is not already here so use curl to get it */
3879566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(localname,tlocalname,llen));
3889566063dSJacob Faibussowitsch       PetscCall(PetscStrcpy(buffer,"curl --fail --silent --show-error "));
3899566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(buffer,url));
3909566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(buffer," > "));
3919566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(buffer,localname));
392e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN)
3939566063dSJacob Faibussowitsch       PetscCall(PetscPOpen(PETSC_COMM_SELF,NULL,buffer,"r",&fp));
3949566063dSJacob Faibussowitsch       PetscCall(PetscPClose(PETSC_COMM_SELF,fp));
395e5c89e4eSSatish Balay #else
396e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
397e5c89e4eSSatish Balay #endif
3989566063dSJacob Faibussowitsch       PetscCall(PetscTestFile(localname,'r',found));
3996e3a5469SBarry Smith       if (*found) {
4006e3a5469SBarry Smith         FILE      *fd;
4016e3a5469SBarry Smith         char      buf[1024],*str,*substring;
4026e3a5469SBarry Smith 
4036e3a5469SBarry Smith         /* check if the file didn't exist so it downloaded an HTML message instead */
4046e3a5469SBarry Smith         fd = fopen(localname,"r");
40528b400f6SJacob Faibussowitsch         PetscCheck(fd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"PetscTestFile() indicates %s exists but fopen() cannot open it",localname);
4066e3a5469SBarry Smith         str = fgets(buf,sizeof(buf)-1,fd);
4076e3a5469SBarry Smith         while (str) {
4089566063dSJacob Faibussowitsch           PetscCall(PetscStrstr(buf,"<!DOCTYPE html>",&substring));
40928b400f6SJacob 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);
4109566063dSJacob Faibussowitsch           PetscCall(PetscStrstr(buf,"Not Found",&substring));
41128b400f6SJacob 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);
4126e3a5469SBarry Smith           str = fgets(buf,sizeof(buf)-1,fd);
4136e3a5469SBarry Smith         }
4146e3a5469SBarry Smith         fclose(fd);
4156e3a5469SBarry Smith       }
41608fb59bfSBarry Smith     } else if (compressed) {
4179566063dSJacob Faibussowitsch       PetscCall(PetscTestFile(url,'r',found));
41808fb59bfSBarry Smith       if (!*found) goto done;
4199566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(localname,url,llen));
42008fb59bfSBarry Smith     }
42108fb59bfSBarry Smith     if (compressed) {
4229566063dSJacob Faibussowitsch       PetscCall(PetscStrrchr(localname,'/',&tlocalname));
4239566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(name,tlocalname,PETSC_MAX_PATH_LEN));
4249566063dSJacob Faibussowitsch       PetscCall(PetscStrstr(name,".gz",&par));
42508fb59bfSBarry Smith       *par = 0; /* remove .gz extension */
42608fb59bfSBarry Smith       /* uncompress file */
4279566063dSJacob Faibussowitsch       PetscCall(PetscStrcpy(buffer,"gzip -c -d "));
4289566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(buffer,localname));
4299566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(buffer," > "));
4309566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(buffer,name));
43108fb59bfSBarry Smith #if defined(PETSC_HAVE_POPEN)
4329566063dSJacob Faibussowitsch       PetscCall(PetscPOpen(PETSC_COMM_SELF,NULL,buffer,"r",&fp));
4339566063dSJacob Faibussowitsch       PetscCall(PetscPClose(PETSC_COMM_SELF,fp));
43408fb59bfSBarry Smith #else
43508fb59bfSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
43608fb59bfSBarry Smith #endif
4379566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(localname,name,llen));
4389566063dSJacob Faibussowitsch       PetscCall(PetscTestFile(localname,'r',found));
439e5c89e4eSSatish Balay     }
440e5c89e4eSSatish Balay   }
441955d42a0SBarry Smith   done:
4429566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(found,1,MPIU_BOOL,0,comm));
4439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(localname, llen, MPI_CHAR, 0, comm));
444e5c89e4eSSatish Balay   PetscFunctionReturn(0);
445e5c89e4eSSatish Balay }
446