]> Git Repo - binutils.git/blob - gprofng/src/DbeFile.cc
Automatic date update in version.in
[binutils.git] / gprofng / src / DbeFile.cc
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2    Contributed by Oracle.
3
4    This file is part of GNU Binutils.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20
21 #include "config.h"
22 #include "util.h"
23 #include "DbeSession.h"
24 #include "Experiment.h"
25 #include "DbeFile.h"
26 #include "ExpGroup.h"
27 #include "DbeJarFile.h"
28
29 DbeFile::DbeFile (const char *filename)
30 {
31   filetype = 0;
32   name = dbe_strdup (filename);
33   name = canonical_path (name);
34   orig_location = NULL;
35   location = NULL;
36   location_info = NULL;
37   jarFile = NULL;
38   container = NULL;
39   need_refind = true;
40   inArchive = false;
41   sbuf.st_atim.tv_sec = 0;
42   experiment = NULL;
43 }
44
45 DbeFile::~DbeFile ()
46 {
47   free (name);
48   free (location);
49   free (orig_location);
50   free (location_info);
51 }
52
53 void
54 DbeFile::set_need_refind (bool val)
55 {
56   if (val != need_refind)
57     {
58       free (location_info);
59       location_info = NULL;
60       need_refind = val;
61     }
62 }
63
64 void
65 DbeFile::set_location (const char *filename)
66 {
67   free (location);
68   location = NULL;
69   if (filename)
70     {
71       if (strncmp (filename, NTXT ("./"), 2) == 0)
72         filename += 2;
73       location = canonical_path (dbe_strdup (filename));
74     }
75   free (location_info);
76   location_info = NULL;
77   set_need_refind (false);
78 }
79
80 char *
81 DbeFile::get_location_info ()
82 {
83   if (location_info == NULL)
84     {
85       char *fnm = get_name ();
86       char *loc = get_location ();
87       Dprintf (DEBUG_DBE_FILE, NTXT ("DbeFile::get_location_info: %s %s\n"),
88                STR (fnm), STR (loc));
89       if (loc == NULL)
90         {
91           if (filetype & F_FICTION)
92             location_info = dbe_strdup (fnm);
93           else
94             location_info = dbe_sprintf (GTXT ("%s (not found)"),
95                                          get_relative_path (fnm));
96         }
97       else
98         {
99           char *r_fnm = get_relative_path (fnm);
100           char *r_loc = get_relative_path (loc);
101           if (strcmp (r_fnm, r_loc) == 0)
102             location_info = dbe_strdup (r_fnm);
103           else
104             {
105               char *bname = get_basename (r_fnm);
106               if (strcmp (bname, r_loc) == 0)  // found in current directory
107                 location_info = dbe_strdup (bname);
108               else
109                 location_info = dbe_sprintf (GTXT ("%s (found as %s)"), bname, r_loc);
110             }
111         }
112     }
113   return location_info;
114 }
115
116 char *
117 DbeFile::getResolvedPath ()
118 {
119   if (get_location ())
120     return location;
121   return name;
122 }
123
124 DbeFile *
125 DbeFile::getJarDbeFile (char *fnm, int sym)
126 {
127   Dprintf (DEBUG_DBE_FILE, NTXT ("DbeFile::getJarDbeFile: %s fnm='%s' sym=%d\n"),
128            STR (name), STR (fnm), sym);
129   DbeFile *df = NULL;
130   if (sym)
131     {
132       char *s = strchr (fnm, sym);
133       if (s)
134         {
135           s = dbe_strndup (fnm, s - fnm);
136           df = dbeSession->getDbeFile (s, F_JAR_FILE | F_FILE);
137           free (s);
138         }
139     }
140   if (df == NULL)
141     df = dbeSession->getDbeFile (fnm, F_JAR_FILE | F_FILE);
142   if (df && (df->experiment == NULL))
143     df->experiment = experiment;
144   return df;
145 }
146
147 char *
148 DbeFile::get_location (bool find_needed)
149 {
150   Dprintf (DEBUG_DBE_FILE, NTXT ("get_location 0x%x %s\n"), filetype, STR (name));
151   if (!find_needed)
152     return need_refind ? NULL : location;
153   if (location || !need_refind)
154     return location;
155   set_need_refind (false);
156   if ((filetype & F_FICTION) != 0)
157     return NULL;
158   if (filetype == F_DIR_OR_JAR)
159     {
160       find_in_archives (name);
161       if (location)
162         {
163           filetype |= F_JAR_FILE | F_FILE;
164           return location;
165         }
166       find_in_pathmap (name);
167       if (location)
168         return location;
169       if (check_access (name) == F_DIRECTORY)
170         {
171           filetype |= F_DIRECTORY;
172           set_location (name);
173           return location;
174         }
175     }
176
177   if ((filetype & F_FILE) != 0)
178     {
179       if (experiment)
180         {
181           char *fnm = experiment->checkFileInArchive (name, false);
182           if (fnm)
183             {
184               set_location (fnm);
185               inArchive = true;
186               sbuf.st_mtime = 0; // Don't check timestamps
187               free (fnm);
188               return location;
189             }
190           if ((filetype & F_JAVACLASS) != 0)
191             {
192               if (orig_location)
193                 {
194                   Dprintf (DEBUG_DBE_FILE, NTXT ("DbeFile::get_location:%d name='%s' orig_location='%s'\n"),
195                            (int) __LINE__, name, orig_location);
196                   // Parse a fileName attribute. There are 4 possibilities:
197                   //   file:<Class_Name>
198                   //   file:<name_of_jar_or_zip_file>
199                   //   jar:file:<name_of_jar_or_zip_file>!<Class_Name>
200                   //   zip:<name_of_jar_or_zip_file>!<Class_Name>
201                   DbeFile *jar_df = NULL;
202                   if (strncmp (orig_location, NTXT ("zip:"), 4) == 0)
203                     jar_df = getJarDbeFile (orig_location + 4, '!');
204                   else if (strncmp (orig_location, NTXT ("jar:file:"), 9) == 0)
205                     jar_df = getJarDbeFile (orig_location + 9, '!');
206                   else if (strncmp (orig_location, NTXT ("file:"), 5) == 0
207                            && isJarOrZip (orig_location + 5))
208                     jar_df = getJarDbeFile (orig_location + 5, 0);
209                   if (jar_df)
210                     {
211                       if (find_in_jar_file (name, jar_df->get_jar_file ()))
212                         {
213                           Dprintf (DEBUG_DBE_FILE, NTXT ("DbeFile::get_location:%d FOUND name='%s' location='%s' jar='%s'\n"),
214                                    (int) __LINE__, name, STR (location), STR (jar_df->get_location ()));
215                           inArchive = jar_df->inArchive;
216                           container = jar_df;
217                           return location;
218                         }
219                     }
220                   if (strncmp (orig_location, NTXT ("file:"), 5) == 0
221                       && !isJarOrZip (orig_location + 5))
222                     {
223                       DbeFile *df = new DbeFile (orig_location + 5);
224                       df->filetype = DbeFile::F_FILE;
225                       df->experiment = experiment;
226                       fnm = df->get_location ();
227                       if (fnm)
228                         {
229                           set_location (fnm);
230                           inArchive = df->inArchive;
231                           sbuf.st_mtime = df->sbuf.st_mtime;
232                           Dprintf (DEBUG_DBE_FILE, NTXT ("DbeFile::get_location:%d FOUND name='%s' orig_location='%s' location='%s'\n"),
233                                    (int) __LINE__, name, orig_location, fnm);
234                           delete df;
235                           return location;
236                         }
237                       delete df;
238                     }
239                 }
240               fnm = dbe_sprintf (NTXT ("%s/%s/%s"), experiment->get_expt_name (), SP_DYNAMIC_CLASSES, name);
241               if (find_file (fnm))
242                 {
243                   inArchive = true;
244                   sbuf.st_mtime = 0; // Don't check timestamps
245                   Dprintf (DEBUG_DBE_FILE, NTXT ("DbeFile::get_location:%d FOUND name='%s' location='%s'\n"),
246                            (int) __LINE__, name, fnm);
247                   free (fnm);
248                   return location;
249                 }
250               free (fnm);
251             }
252         }
253     }
254
255   if (dbeSession->archive_mode)
256     {
257       find_file (name);
258       if (location)
259         return location;
260     }
261
262   bool inPathMap = find_in_pathmap (name);
263   if (location)
264     return location;
265   find_in_setpath (name, dbeSession->get_search_path ());
266   if (location)
267     return location;
268   if ((filetype & (F_JAVACLASS | F_JAVA_SOURCE)) != 0)
269     {
270       find_in_classpath (name, dbeSession->get_classpath ());
271       if (location)
272         return location;
273     }
274   if (!inPathMap)
275     find_file (name);
276   Dprintf (DEBUG_DBE_FILE && (location == NULL),
277            "DbeFile::get_location:%d NOT FOUND name='%s'\n", __LINE__, name);
278   return location;
279 }
280
281 int
282 DbeFile::check_access (const char *filename)
283 {
284   if (filename == NULL)
285     return F_NOT_FOUND;
286   int st = dbe_stat (filename, &sbuf);
287   Dprintf (DEBUG_DBE_FILE, NTXT ("check_access: %d 0x%x %s\n"), st, filetype, filename);
288   if (st == 0)
289     {
290       if (S_ISDIR (sbuf.st_mode))
291         return F_DIRECTORY;
292       else if (S_ISREG (sbuf.st_mode))
293         return F_FILE;
294       return F_UNKNOWN; // Symbolic link or unknown type of file
295     }
296   sbuf.st_atim.tv_sec = 0;
297   sbuf.st_mtime = 0; // Don't check timestamps
298   return F_NOT_FOUND; // File not found
299 }
300
301 bool
302 DbeFile::isJarOrZip (const char *fnm)
303 {
304   size_t len = strlen (fnm) - 4;
305   return len > 0 && (strcmp (fnm + len, NTXT (".jar")) == 0
306                      || strcmp (fnm + len, NTXT (".zip")) == 0);
307 }
308
309 char *
310 DbeFile::find_file (const char *filename)
311 {
312   switch (check_access (filename))
313     {
314     case F_DIRECTORY:
315       if (filetype == F_DIR_OR_JAR)
316         filetype |= F_DIRECTORY;
317       if ((filetype & F_DIRECTORY) != 0)
318         set_location (filename);
319       break;
320     case F_FILE:
321       if (filetype == F_DIR_OR_JAR)
322         {
323           filetype |= F_FILE;
324           if (isJarOrZip (filename))
325             filetype |= F_JAR_FILE;
326         }
327       if ((filetype & F_DIRECTORY) == 0)
328         set_location (filename);
329       break;
330     }
331   return location;
332 }
333
334 DbeJarFile *
335 DbeFile::get_jar_file ()
336 {
337   if (jarFile == NULL)
338     {
339       char *fnm = get_location ();
340       if (fnm)
341         jarFile = dbeSession->get_JarFile (fnm);
342     }
343   return jarFile;
344 }
345
346 char *
347 DbeFile::find_package_name (const char *filename, const char *dirname)
348 {
349   char *nm = dbe_sprintf (NTXT ("%s/%s"), dirname, filename);
350   if (!find_in_pathmap (nm))
351     find_file (nm);
352   free (nm);
353   return location;
354 }
355
356 char *
357 DbeFile::find_in_directory (const char *filename, const char *dirname)
358 {
359   if (filename && dirname)
360     {
361       char *nm = dbe_sprintf (NTXT ("%s/%s"), dirname, filename);
362       find_file (nm);
363       free (nm);
364     }
365   return location;
366 }
367
368 char *
369 DbeFile::find_in_jar_file (const char *filename, DbeJarFile *jfile)
370 {
371   // Read .jar or .zip
372   if (jfile == NULL)
373     return NULL;
374   int entry = jfile->get_entry (filename);
375   if (entry >= 0)
376     {
377       char *fnm = dbeSession->get_tmp_file_name (filename, true);
378       long long fsize = jfile->copy (fnm, entry);
379       if (fsize >= 0)
380         {
381           dbeSession->tmp_files->append (fnm);
382           set_location (fnm);
383           sbuf.st_size = fsize;
384           sbuf.st_mtime = 0; // Don't check timestamps
385           fnm = NULL;
386         }
387       free (fnm);
388     }
389   return location;
390 }
391
392 bool
393 DbeFile::find_in_pathmap (char *filename)
394 {
395   Vector<pathmap_t*> *pathmaps = dbeSession->get_pathmaps ();
396   bool inPathMap = false;
397   if (strncmp (filename, NTXT ("./"), 2) == 0)
398     filename += 2;
399   for (int i = 0, sz = pathmaps ? pathmaps->size () : 0; i < sz; i++)
400     {
401       pathmap_t *pmp = pathmaps->fetch (i);
402       size_t len = strlen (pmp->old_prefix);
403       if (strncmp (pmp->old_prefix, filename, len) == 0
404           && (filename[len] == '/' || filename[len] == '\0'))
405         {
406           inPathMap = true;
407           if (find_in_directory (filename + len, pmp->new_prefix))
408             {
409               return inPathMap;
410             }
411         }
412     }
413   return inPathMap;
414 }
415
416 void
417 DbeFile::find_in_archives (char *filename)
418 {
419   for (int i1 = 0, sz1 = dbeSession->expGroups->size (); i1 < sz1; i1++)
420     {
421       ExpGroup *gr = dbeSession->expGroups->fetch (i1);
422       if (gr->founder)
423         {
424           char *nm = gr->founder->checkFileInArchive (filename, false);
425           if (nm)
426             {
427               find_file (nm);
428               if (location)
429                 {
430                   sbuf.st_mtime = 0; // Don't check timestamps
431                   return;
432                 }
433             }
434         }
435     }
436 }
437
438 void
439 DbeFile::find_in_setpath (char *filename, Vector<char*> *searchPath)
440 {
441   char *base = get_basename (filename);
442   for (int i = 0, sz = searchPath ? searchPath->size () : 0; i < sz; i++)
443     {
444       char *spath = searchPath->fetch (i);
445       // Check file in each experiment directory
446       if (streq (spath, "$") || streq (spath, NTXT ("$expts")))
447         {
448           // find only in founders and only LoadObj.
449           for (int i1 = 0, sz1 = dbeSession->expGroups->size (); i1 < sz1; i1++)
450             {
451               ExpGroup *gr = dbeSession->expGroups->fetch (i1);
452               char *exp_name = gr->founder->get_expt_name ();
453               if (gr->founder)
454                 {
455                   if ((filetype & (F_JAVACLASS | F_JAVA_SOURCE)) != 0)
456                     {
457                       // Find with the package name
458                       if (find_in_directory (filename, exp_name))
459                          return;
460                     }
461                   if (find_in_directory (base, exp_name))
462                     return;
463                 }
464             }
465           continue;
466         }
467       DbeFile *df = dbeSession->getDbeFile (spath, DbeFile::F_DIR_OR_JAR);
468       if (df->get_location () == NULL)
469         continue;
470       if ((filetype & (F_JAVACLASS | F_JAVA_SOURCE)) != 0)
471         {
472           if ((df->filetype & F_JAR_FILE) != 0)
473             {
474               if (find_in_jar_file (filename, df->get_jar_file ()))
475                 {
476                   container = df;
477                   return;
478                 }
479               continue;
480             }
481           else if ((df->filetype & F_DIRECTORY) != 0)
482             // Find with the package name
483             if (find_package_name (filename, spath))
484               return;
485         }
486       if ((df->filetype & F_DIRECTORY) != 0)
487         if (find_in_directory (base, df->get_location ()))
488           return;
489     }
490 }
491
492 void
493 DbeFile::find_in_classpath (char *filename, Vector<DbeFile*> *classPath)
494 {
495   for (int i = 0, sz = classPath ? classPath->size () : 0; i < sz; i++)
496     {
497       DbeFile *df = classPath->fetch (i);
498       if (df->get_location () == NULL)
499         continue;
500       if ((df->filetype & F_JAR_FILE) != 0)
501         {
502           if (find_in_jar_file (filename, df->get_jar_file ()))
503             {
504               container = df;
505               return;
506             }
507         }
508       else if ((df->filetype & F_DIRECTORY) != 0)
509         // Find with the package name
510         if (find_package_name (filename, df->get_name ()))
511           return;
512     }
513 }
514
515 struct stat64 *
516 DbeFile::get_stat ()
517 {
518   if (sbuf.st_atim.tv_sec == 0)
519     {
520       int st = check_access (get_location (false));
521       if (st == F_NOT_FOUND)
522         return NULL;
523     }
524   return &sbuf;
525 }
526
527 bool
528 DbeFile::compare (DbeFile *df)
529 {
530   if (df == NULL)
531     return false;
532   struct stat64 *st1 = get_stat ();
533   struct stat64 *st2 = df->get_stat ();
534   if (st1 == NULL || st2 == NULL)
535     return false;
536   if (st1->st_size != st2->st_size)
537     return false;
538   if (st1->st_mtim.tv_sec != st2->st_mtim.tv_sec)
539     return false;
540   return true;
541 }
This page took 0.054857 seconds and 4 git commands to generate.