xref: /aosp_15_r20/external/pciutils/lib/names-cache.c (revision c2e0c6b56a71da9abe8df5c8348fb3eb5c2c9251)
1*c2e0c6b5SAndroid Build Coastguard Worker /*
2*c2e0c6b5SAndroid Build Coastguard Worker  *	The PCI Library -- ID to Name Cache
3*c2e0c6b5SAndroid Build Coastguard Worker  *
4*c2e0c6b5SAndroid Build Coastguard Worker  *	Copyright (c) 2008--2009 Martin Mares <[email protected]>
5*c2e0c6b5SAndroid Build Coastguard Worker  *
6*c2e0c6b5SAndroid Build Coastguard Worker  *	Can be freely distributed and used under the terms of the GNU GPL v2+.
7*c2e0c6b5SAndroid Build Coastguard Worker  *
8*c2e0c6b5SAndroid Build Coastguard Worker  *	SPDX-License-Identifier: GPL-2.0-or-later
9*c2e0c6b5SAndroid Build Coastguard Worker  */
10*c2e0c6b5SAndroid Build Coastguard Worker 
11*c2e0c6b5SAndroid Build Coastguard Worker #include "internal.h"
12*c2e0c6b5SAndroid Build Coastguard Worker #include "names.h"
13*c2e0c6b5SAndroid Build Coastguard Worker 
14*c2e0c6b5SAndroid Build Coastguard Worker #ifdef PCI_USE_DNS
15*c2e0c6b5SAndroid Build Coastguard Worker 
16*c2e0c6b5SAndroid Build Coastguard Worker #include <stdio.h>
17*c2e0c6b5SAndroid Build Coastguard Worker #include <stdlib.h>
18*c2e0c6b5SAndroid Build Coastguard Worker #include <string.h>
19*c2e0c6b5SAndroid Build Coastguard Worker #include <errno.h>
20*c2e0c6b5SAndroid Build Coastguard Worker #include <sys/types.h>
21*c2e0c6b5SAndroid Build Coastguard Worker #include <sys/stat.h>
22*c2e0c6b5SAndroid Build Coastguard Worker #include <pwd.h>
23*c2e0c6b5SAndroid Build Coastguard Worker #include <unistd.h>
24*c2e0c6b5SAndroid Build Coastguard Worker 
25*c2e0c6b5SAndroid Build Coastguard Worker static const char cache_version[] = "#PCI-CACHE-1.0";
26*c2e0c6b5SAndroid Build Coastguard Worker 
get_cache_name(struct pci_access * a)27*c2e0c6b5SAndroid Build Coastguard Worker static char *get_cache_name(struct pci_access *a)
28*c2e0c6b5SAndroid Build Coastguard Worker {
29*c2e0c6b5SAndroid Build Coastguard Worker   if (!a->id_cache_name)
30*c2e0c6b5SAndroid Build Coastguard Worker     {
31*c2e0c6b5SAndroid Build Coastguard Worker       char *name = pci_get_param(a, "net.cache_name");
32*c2e0c6b5SAndroid Build Coastguard Worker       if (!name || !name[0])
33*c2e0c6b5SAndroid Build Coastguard Worker 	return NULL;
34*c2e0c6b5SAndroid Build Coastguard Worker 
35*c2e0c6b5SAndroid Build Coastguard Worker       if (strncmp(name, "~/", 2))
36*c2e0c6b5SAndroid Build Coastguard Worker 	a->id_cache_name = pci_strdup(a, name);
37*c2e0c6b5SAndroid Build Coastguard Worker       else
38*c2e0c6b5SAndroid Build Coastguard Worker 	{
39*c2e0c6b5SAndroid Build Coastguard Worker 	  uid_t uid = getuid();
40*c2e0c6b5SAndroid Build Coastguard Worker 	  struct passwd *pw = getpwuid(uid);
41*c2e0c6b5SAndroid Build Coastguard Worker 	  if (!pw)
42*c2e0c6b5SAndroid Build Coastguard Worker 	    return name;
43*c2e0c6b5SAndroid Build Coastguard Worker 
44*c2e0c6b5SAndroid Build Coastguard Worker 	  a->id_cache_name = pci_malloc(a, strlen(pw->pw_dir) + strlen(name+1) + 1);
45*c2e0c6b5SAndroid Build Coastguard Worker 	  sprintf(a->id_cache_name, "%s%s", pw->pw_dir, name+1);
46*c2e0c6b5SAndroid Build Coastguard Worker 	}
47*c2e0c6b5SAndroid Build Coastguard Worker     }
48*c2e0c6b5SAndroid Build Coastguard Worker 
49*c2e0c6b5SAndroid Build Coastguard Worker   return a->id_cache_name;
50*c2e0c6b5SAndroid Build Coastguard Worker }
51*c2e0c6b5SAndroid Build Coastguard Worker 
create_parent_dirs(struct pci_access * a,char * name)52*c2e0c6b5SAndroid Build Coastguard Worker static void create_parent_dirs(struct pci_access *a, char *name)
53*c2e0c6b5SAndroid Build Coastguard Worker {
54*c2e0c6b5SAndroid Build Coastguard Worker   // Assumes that we have a private copy of the name we can modify
55*c2e0c6b5SAndroid Build Coastguard Worker 
56*c2e0c6b5SAndroid Build Coastguard Worker   char *p = name + strlen(name);
57*c2e0c6b5SAndroid Build Coastguard Worker   while (p > name && *p != '/')
58*c2e0c6b5SAndroid Build Coastguard Worker     p--;
59*c2e0c6b5SAndroid Build Coastguard Worker   if (p == name)
60*c2e0c6b5SAndroid Build Coastguard Worker     return;
61*c2e0c6b5SAndroid Build Coastguard Worker 
62*c2e0c6b5SAndroid Build Coastguard Worker   while (p > name)
63*c2e0c6b5SAndroid Build Coastguard Worker     {
64*c2e0c6b5SAndroid Build Coastguard Worker       // We stand at a slash. Check if the current prefix exists.
65*c2e0c6b5SAndroid Build Coastguard Worker       *p = 0;
66*c2e0c6b5SAndroid Build Coastguard Worker       struct stat st;
67*c2e0c6b5SAndroid Build Coastguard Worker       int res = stat(name, &st);
68*c2e0c6b5SAndroid Build Coastguard Worker       *p = '/';
69*c2e0c6b5SAndroid Build Coastguard Worker       if (res >= 0)
70*c2e0c6b5SAndroid Build Coastguard Worker 	break;
71*c2e0c6b5SAndroid Build Coastguard Worker 
72*c2e0c6b5SAndroid Build Coastguard Worker       // Does not exist yet, move up one directory
73*c2e0c6b5SAndroid Build Coastguard Worker       p--;
74*c2e0c6b5SAndroid Build Coastguard Worker       while (p > name && *p != '/')
75*c2e0c6b5SAndroid Build Coastguard Worker 	p--;
76*c2e0c6b5SAndroid Build Coastguard Worker     }
77*c2e0c6b5SAndroid Build Coastguard Worker 
78*c2e0c6b5SAndroid Build Coastguard Worker   // We now stand at the end of the longest existing prefix.
79*c2e0c6b5SAndroid Build Coastguard Worker   // Create all directories to the right of it.
80*c2e0c6b5SAndroid Build Coastguard Worker   for (;;)
81*c2e0c6b5SAndroid Build Coastguard Worker     {
82*c2e0c6b5SAndroid Build Coastguard Worker       p++;
83*c2e0c6b5SAndroid Build Coastguard Worker       while (*p && *p != '/')
84*c2e0c6b5SAndroid Build Coastguard Worker 	p++;
85*c2e0c6b5SAndroid Build Coastguard Worker       if (!*p)
86*c2e0c6b5SAndroid Build Coastguard Worker 	break;
87*c2e0c6b5SAndroid Build Coastguard Worker 
88*c2e0c6b5SAndroid Build Coastguard Worker       *p = 0;
89*c2e0c6b5SAndroid Build Coastguard Worker       int res = mkdir(name, 0777);
90*c2e0c6b5SAndroid Build Coastguard Worker       if (res < 0)
91*c2e0c6b5SAndroid Build Coastguard Worker 	{
92*c2e0c6b5SAndroid Build Coastguard Worker 	  a->warning("Cannot create directory %s: %s", name, strerror(errno));
93*c2e0c6b5SAndroid Build Coastguard Worker 	  *p = '/';
94*c2e0c6b5SAndroid Build Coastguard Worker 	  break;
95*c2e0c6b5SAndroid Build Coastguard Worker 	}
96*c2e0c6b5SAndroid Build Coastguard Worker       *p = '/';
97*c2e0c6b5SAndroid Build Coastguard Worker     }
98*c2e0c6b5SAndroid Build Coastguard Worker }
99*c2e0c6b5SAndroid Build Coastguard Worker 
100*c2e0c6b5SAndroid Build Coastguard Worker int
pci_id_cache_load(struct pci_access * a,int flags)101*c2e0c6b5SAndroid Build Coastguard Worker pci_id_cache_load(struct pci_access *a, int flags)
102*c2e0c6b5SAndroid Build Coastguard Worker {
103*c2e0c6b5SAndroid Build Coastguard Worker   char *name;
104*c2e0c6b5SAndroid Build Coastguard Worker   char line[MAX_LINE];
105*c2e0c6b5SAndroid Build Coastguard Worker   FILE *f;
106*c2e0c6b5SAndroid Build Coastguard Worker   int lino;
107*c2e0c6b5SAndroid Build Coastguard Worker 
108*c2e0c6b5SAndroid Build Coastguard Worker   if (a->id_cache_status > 0)
109*c2e0c6b5SAndroid Build Coastguard Worker     return 0;
110*c2e0c6b5SAndroid Build Coastguard Worker   a->id_cache_status = 1;
111*c2e0c6b5SAndroid Build Coastguard Worker 
112*c2e0c6b5SAndroid Build Coastguard Worker   name = get_cache_name(a);
113*c2e0c6b5SAndroid Build Coastguard Worker   if (!name)
114*c2e0c6b5SAndroid Build Coastguard Worker     return 0;
115*c2e0c6b5SAndroid Build Coastguard Worker   a->debug("Using cache %s\n", name);
116*c2e0c6b5SAndroid Build Coastguard Worker 
117*c2e0c6b5SAndroid Build Coastguard Worker   if (flags & PCI_LOOKUP_REFRESH_CACHE)
118*c2e0c6b5SAndroid Build Coastguard Worker     {
119*c2e0c6b5SAndroid Build Coastguard Worker       a->debug("Not loading cache, will refresh everything\n");
120*c2e0c6b5SAndroid Build Coastguard Worker       a->id_cache_status = 2;
121*c2e0c6b5SAndroid Build Coastguard Worker       return 0;
122*c2e0c6b5SAndroid Build Coastguard Worker     }
123*c2e0c6b5SAndroid Build Coastguard Worker 
124*c2e0c6b5SAndroid Build Coastguard Worker   f = fopen(name, "rb");
125*c2e0c6b5SAndroid Build Coastguard Worker   if (!f)
126*c2e0c6b5SAndroid Build Coastguard Worker     {
127*c2e0c6b5SAndroid Build Coastguard Worker       a->debug("Cache file does not exist\n");
128*c2e0c6b5SAndroid Build Coastguard Worker       return 0;
129*c2e0c6b5SAndroid Build Coastguard Worker     }
130*c2e0c6b5SAndroid Build Coastguard Worker   /* FIXME: Compare timestamp with the pci.ids file? */
131*c2e0c6b5SAndroid Build Coastguard Worker 
132*c2e0c6b5SAndroid Build Coastguard Worker   lino = 0;
133*c2e0c6b5SAndroid Build Coastguard Worker   while (fgets(line, sizeof(line), f))
134*c2e0c6b5SAndroid Build Coastguard Worker     {
135*c2e0c6b5SAndroid Build Coastguard Worker       char *p = strchr(line, '\n');
136*c2e0c6b5SAndroid Build Coastguard Worker       lino++;
137*c2e0c6b5SAndroid Build Coastguard Worker       if (p)
138*c2e0c6b5SAndroid Build Coastguard Worker         {
139*c2e0c6b5SAndroid Build Coastguard Worker 	  *p = 0;
140*c2e0c6b5SAndroid Build Coastguard Worker 	  if (lino == 1)
141*c2e0c6b5SAndroid Build Coastguard Worker 	    {
142*c2e0c6b5SAndroid Build Coastguard Worker 	      if (strcmp(line, cache_version))
143*c2e0c6b5SAndroid Build Coastguard Worker 	        {
144*c2e0c6b5SAndroid Build Coastguard Worker 		  a->debug("Unrecognized cache version %s, ignoring\n", line);
145*c2e0c6b5SAndroid Build Coastguard Worker 		  break;
146*c2e0c6b5SAndroid Build Coastguard Worker 		}
147*c2e0c6b5SAndroid Build Coastguard Worker 	      continue;
148*c2e0c6b5SAndroid Build Coastguard Worker 	    }
149*c2e0c6b5SAndroid Build Coastguard Worker 	  else
150*c2e0c6b5SAndroid Build Coastguard Worker 	    {
151*c2e0c6b5SAndroid Build Coastguard Worker 	      int cat, id1, id2, id3, id4, cnt;
152*c2e0c6b5SAndroid Build Coastguard Worker 	      if (sscanf(line, "%d%x%x%x%x%n", &cat, &id1, &id2, &id3, &id4, &cnt) >= 5)
153*c2e0c6b5SAndroid Build Coastguard Worker 	        {
154*c2e0c6b5SAndroid Build Coastguard Worker 		  p = line + cnt;
155*c2e0c6b5SAndroid Build Coastguard Worker 		  while (*p && *p == ' ')
156*c2e0c6b5SAndroid Build Coastguard Worker 		    p++;
157*c2e0c6b5SAndroid Build Coastguard Worker 		  pci_id_insert(a, cat, id1, id2, id3, id4, p, SRC_CACHE);
158*c2e0c6b5SAndroid Build Coastguard Worker 		  continue;
159*c2e0c6b5SAndroid Build Coastguard Worker 		}
160*c2e0c6b5SAndroid Build Coastguard Worker 	    }
161*c2e0c6b5SAndroid Build Coastguard Worker 	}
162*c2e0c6b5SAndroid Build Coastguard Worker       a->warning("Malformed cache file %s (line %d), ignoring", name, lino);
163*c2e0c6b5SAndroid Build Coastguard Worker       break;
164*c2e0c6b5SAndroid Build Coastguard Worker     }
165*c2e0c6b5SAndroid Build Coastguard Worker 
166*c2e0c6b5SAndroid Build Coastguard Worker   if (ferror(f))
167*c2e0c6b5SAndroid Build Coastguard Worker     a->warning("Error while reading %s", name);
168*c2e0c6b5SAndroid Build Coastguard Worker   fclose(f);
169*c2e0c6b5SAndroid Build Coastguard Worker   return 1;
170*c2e0c6b5SAndroid Build Coastguard Worker }
171*c2e0c6b5SAndroid Build Coastguard Worker 
172*c2e0c6b5SAndroid Build Coastguard Worker void
pci_id_cache_flush(struct pci_access * a)173*c2e0c6b5SAndroid Build Coastguard Worker pci_id_cache_flush(struct pci_access *a)
174*c2e0c6b5SAndroid Build Coastguard Worker {
175*c2e0c6b5SAndroid Build Coastguard Worker   int orig_status = a->id_cache_status;
176*c2e0c6b5SAndroid Build Coastguard Worker   FILE *f;
177*c2e0c6b5SAndroid Build Coastguard Worker   unsigned int h;
178*c2e0c6b5SAndroid Build Coastguard Worker   struct id_entry *e, *e2;
179*c2e0c6b5SAndroid Build Coastguard Worker   char hostname[256], *tmpname, *name;
180*c2e0c6b5SAndroid Build Coastguard Worker   int this_pid;
181*c2e0c6b5SAndroid Build Coastguard Worker 
182*c2e0c6b5SAndroid Build Coastguard Worker   a->id_cache_status = 0;
183*c2e0c6b5SAndroid Build Coastguard Worker   if (orig_status < 2)
184*c2e0c6b5SAndroid Build Coastguard Worker     return;
185*c2e0c6b5SAndroid Build Coastguard Worker   name = get_cache_name(a);
186*c2e0c6b5SAndroid Build Coastguard Worker   if (!name)
187*c2e0c6b5SAndroid Build Coastguard Worker     return;
188*c2e0c6b5SAndroid Build Coastguard Worker 
189*c2e0c6b5SAndroid Build Coastguard Worker   create_parent_dirs(a, name);
190*c2e0c6b5SAndroid Build Coastguard Worker 
191*c2e0c6b5SAndroid Build Coastguard Worker   this_pid = getpid();
192*c2e0c6b5SAndroid Build Coastguard Worker   if (gethostname(hostname, sizeof(hostname)) < 0)
193*c2e0c6b5SAndroid Build Coastguard Worker     hostname[0] = 0;
194*c2e0c6b5SAndroid Build Coastguard Worker   else
195*c2e0c6b5SAndroid Build Coastguard Worker     hostname[sizeof(hostname)-1] = 0;
196*c2e0c6b5SAndroid Build Coastguard Worker   tmpname = pci_malloc(a, strlen(name) + strlen(hostname) + 64);
197*c2e0c6b5SAndroid Build Coastguard Worker   sprintf(tmpname, "%s.tmp-%s-%d", name, hostname, this_pid);
198*c2e0c6b5SAndroid Build Coastguard Worker 
199*c2e0c6b5SAndroid Build Coastguard Worker   f = fopen(tmpname, "wb");
200*c2e0c6b5SAndroid Build Coastguard Worker   if (!f)
201*c2e0c6b5SAndroid Build Coastguard Worker     {
202*c2e0c6b5SAndroid Build Coastguard Worker       a->warning("Cannot write to %s: %s", name, strerror(errno));
203*c2e0c6b5SAndroid Build Coastguard Worker       pci_mfree(tmpname);
204*c2e0c6b5SAndroid Build Coastguard Worker       return;
205*c2e0c6b5SAndroid Build Coastguard Worker     }
206*c2e0c6b5SAndroid Build Coastguard Worker   a->debug("Writing cache to %s\n", name);
207*c2e0c6b5SAndroid Build Coastguard Worker   fprintf(f, "%s\n", cache_version);
208*c2e0c6b5SAndroid Build Coastguard Worker 
209*c2e0c6b5SAndroid Build Coastguard Worker   for (h=0; h<HASH_SIZE; h++)
210*c2e0c6b5SAndroid Build Coastguard Worker     for (e=a->id_hash[h]; e; e=e->next)
211*c2e0c6b5SAndroid Build Coastguard Worker       if (e->src == SRC_CACHE || e->src == SRC_NET)
212*c2e0c6b5SAndroid Build Coastguard Worker 	{
213*c2e0c6b5SAndroid Build Coastguard Worker 	  /* Negative entries are not written */
214*c2e0c6b5SAndroid Build Coastguard Worker 	  if (!e->name[0])
215*c2e0c6b5SAndroid Build Coastguard Worker 	    continue;
216*c2e0c6b5SAndroid Build Coastguard Worker 
217*c2e0c6b5SAndroid Build Coastguard Worker 	  /* Verify that every entry is written at most once */
218*c2e0c6b5SAndroid Build Coastguard Worker 	  for (e2=a->id_hash[h]; e2 != e; e2=e2->next)
219*c2e0c6b5SAndroid Build Coastguard Worker 	    if ((e2->src == SRC_CACHE || e2->src == SRC_NET) &&
220*c2e0c6b5SAndroid Build Coastguard Worker 	        e2->cat == e->cat &&
221*c2e0c6b5SAndroid Build Coastguard Worker 		e2->id12 == e->id12 && e2->id34 == e->id34)
222*c2e0c6b5SAndroid Build Coastguard Worker 	    break;
223*c2e0c6b5SAndroid Build Coastguard Worker 	  if (e2 == e)
224*c2e0c6b5SAndroid Build Coastguard Worker 	    fprintf(f, "%d %x %x %x %x %s\n",
225*c2e0c6b5SAndroid Build Coastguard Worker 	            e->cat,
226*c2e0c6b5SAndroid Build Coastguard Worker 		    pair_first(e->id12), pair_second(e->id12),
227*c2e0c6b5SAndroid Build Coastguard Worker 		    pair_first(e->id34), pair_second(e->id34),
228*c2e0c6b5SAndroid Build Coastguard Worker 		    e->name);
229*c2e0c6b5SAndroid Build Coastguard Worker 	}
230*c2e0c6b5SAndroid Build Coastguard Worker 
231*c2e0c6b5SAndroid Build Coastguard Worker   fflush(f);
232*c2e0c6b5SAndroid Build Coastguard Worker   if (ferror(f))
233*c2e0c6b5SAndroid Build Coastguard Worker     a->warning("Error writing %s", name);
234*c2e0c6b5SAndroid Build Coastguard Worker   fclose(f);
235*c2e0c6b5SAndroid Build Coastguard Worker 
236*c2e0c6b5SAndroid Build Coastguard Worker   if (rename(tmpname, name) < 0)
237*c2e0c6b5SAndroid Build Coastguard Worker     {
238*c2e0c6b5SAndroid Build Coastguard Worker       a->warning("Cannot rename %s to %s: %s", tmpname, name, strerror(errno));
239*c2e0c6b5SAndroid Build Coastguard Worker       unlink(tmpname);
240*c2e0c6b5SAndroid Build Coastguard Worker     }
241*c2e0c6b5SAndroid Build Coastguard Worker   pci_mfree(tmpname);
242*c2e0c6b5SAndroid Build Coastguard Worker }
243*c2e0c6b5SAndroid Build Coastguard Worker 
244*c2e0c6b5SAndroid Build Coastguard Worker #else
245*c2e0c6b5SAndroid Build Coastguard Worker 
pci_id_cache_load(struct pci_access * a UNUSED,int flags UNUSED)246*c2e0c6b5SAndroid Build Coastguard Worker int pci_id_cache_load(struct pci_access *a UNUSED, int flags UNUSED)
247*c2e0c6b5SAndroid Build Coastguard Worker {
248*c2e0c6b5SAndroid Build Coastguard Worker   a->id_cache_status = 1;
249*c2e0c6b5SAndroid Build Coastguard Worker   return 0;
250*c2e0c6b5SAndroid Build Coastguard Worker }
251*c2e0c6b5SAndroid Build Coastguard Worker 
pci_id_cache_flush(struct pci_access * a)252*c2e0c6b5SAndroid Build Coastguard Worker void pci_id_cache_flush(struct pci_access *a)
253*c2e0c6b5SAndroid Build Coastguard Worker {
254*c2e0c6b5SAndroid Build Coastguard Worker   a->id_cache_status = 0;
255*c2e0c6b5SAndroid Build Coastguard Worker   pci_mfree(a->id_cache_name);
256*c2e0c6b5SAndroid Build Coastguard Worker   a->id_cache_name = NULL;
257*c2e0c6b5SAndroid Build Coastguard Worker }
258*c2e0c6b5SAndroid Build Coastguard Worker 
259*c2e0c6b5SAndroid Build Coastguard Worker #endif
260*c2e0c6b5SAndroid Build Coastguard Worker 
261*c2e0c6b5SAndroid Build Coastguard Worker void
pci_id_cache_dirty(struct pci_access * a)262*c2e0c6b5SAndroid Build Coastguard Worker pci_id_cache_dirty(struct pci_access *a)
263*c2e0c6b5SAndroid Build Coastguard Worker {
264*c2e0c6b5SAndroid Build Coastguard Worker   if (a->id_cache_status >= 1)
265*c2e0c6b5SAndroid Build Coastguard Worker     a->id_cache_status = 2;
266*c2e0c6b5SAndroid Build Coastguard Worker }
267